先上代码
export interface Store {
[key: string]: any;
}
type OnFinishCallback = (values: Store) => void;
export interface Callbacks {
onFinish?: OnFinishCallback;
}
export interface TestData {
name: string;
password: string;
age: number;
}
const test1: OnFinishCallback = (values: TestData) => {};
const test2: Callbacks['onFinish'] = (values: TestData) => {};
抛出问题
Typescript 版本:3.7.5
提问:为什么不能匹配泛型接口?单纯好奇,也知道可以通过 <T>
或者中间函数传递来解决。
1
johnnyNg 2020-03-03 14:01:45 +08:00
说的是 TestData 和 Store 类型不符合,把 TestData 改成 Store 就好了
|
2
mxT52CRuqR6o5 2020-03-03 14:04:18 +08:00 via Android
泛型在哪?
|
3
HanMeiM OP @mxT52CRuqR6o5 害,俺说错了,泛型能匹配上,但是直接这样写 索引签名 不行。
|
4
chuxiaonan 2020-03-03 14:18:02 +08:00
export interface TestData extends Store {
... } |
5
HanMeiM OP @chuxiaonan 不行哦,我试过的。
|
6
chuxiaonan 2020-03-03 14:51:36 +08:00
@HanMeiM 这样噢 那就不是很了解啦
|
7
myl0204 2020-03-03 15:03:32 +08:00
我的理解是实际函数的参数类型是确定的:`TestData `,而 OnFinishCallback 中参数类型其实是不定的,可以是`{a: 1, b:2}`也可以是`{c: 3}`等等。
这二者当然不匹配呀 |
8
maichael 2020-03-03 15:26:00 +08:00
因为 Store 类型的值不能赋值给 TestData 类型的变量。你对泛型的理解是有问题的,你想,假设你整个逻辑成立,那你这里的 test1 函数入参就是 Store 类型的变量,但是 Store 类型的变量未必能赋值给 TestData 类型的变量,所以逻辑上不通。反过来才是对的,但意图就可能跟你原有的不一致了,你可以说下你的需求是啥吗
type OnFinishCallback = (values: TestData) => void; const test1: OnFinishCallback = (values: Store) => {}; |
9
geelaw 2020-03-03 15:41:12 +08:00 3
Store 是水果,TestData 是橘子,OnFinishCallback 是“能处理任意水果”的类型。因为 test1 初始化的表达式不能处理任意水果(只能处理橘子),所以不行。
用术语来说是 A => void 对 A 是逆变,如果 B is-an A,则 (A => void) is-a (B => void),而不是反过来。 |
10
HanMeiM OP @maichael
@geelaw 其实也不是我写成这样,我肯定还是希望用泛型去解决。 我还是直接说我在哪遇到的问题吧。 我今天更新 Ant-Design 4.0.0 的时候,Form 组件有很大的改变。 官方推荐使用 `Form` 组件的 `onFinish` 属性来获取表单值。 下面是这个属性的定义。 ![image.png]( https://i.loli.net/2020/03/03/fGa5TFlbCqAWZtJ.png) ![image.png]( https://i.loli.net/2020/03/03/JOx3lFEbDmCwWqA.png) ![image.png]( https://i.loli.net/2020/03/03/Um3qOG2BRAMy4xt.png) 然后上图的 `test2` 就是我写的获取表单的方法,很明显会报错,所以有点头疼。 目前是直接在 `Form` 表单中这样写来解决 ```Typescript onFinish={(value: Store) => test2(value)} ``` |
11
maichael 2020-03-03 17:29:31 +08:00 1
@HanMeiM #10 暂时没有,这个 Antd 这个东西的问题。
https://github.com/ant-design/ant-design/issues/21195 https://github.com/react-component/field-form/issues/70 简单来说,他这里本应该提供 "Generic type arguments" 来自定义 StoreValue 的类型,但他没有给,所以你从外部没法去改变他内部的类型。你现在只能强转类型然后等他修好。 |
13
buffzty 2020-03-03 20:54:20 +08:00
TestData 类型是兼容 Store 的,但是 (v: TestData )=>{} 这个函数类型 是不兼容 (v: Store)=>{} 这个函数类型的
可能是 ts 为了检测简单,不然还要把所有函数的参数再检测一遍. 我的建议: 去掉函数形参中的类型,此时 ts 会自动推断为 Store 传参时可以传 TestData 类型. 以下代码在 3.7.5 无报错 ```typescript export interface Store { title: string // 加这个只是为了测试自动推断 [key: string]: any } type OnFinishCallback = (values: Store) => void export interface Callbacks { onFinish?: OnFinishCallback } export type TestData = Store & { name: string password: string age: number } let a: TestData = { b: 123, age: 12, name: '1', password: '', title: '' } let b: Store = a const test1: OnFinishCallback = values => { console.log(values.title) // 这里的 values 已经被自动推断过了 } const test2: Callbacks['onFinish'] = values => { console.log(values.title) } test1(a) test1(b) test2(a) test2(b) ``` |
14
Mistwave 2020-03-03 21:11:09 +08:00
|
17
xiaojie668329 2020-03-03 21:49:42 +08:00
TestData 的类型显然更具体了,它的类型被收窄(narrow down)了,test1 中的 values 的限制更多,不匹配 OnFinishCallback 中的 Store。也就是,OnFinishCallback 的 values 参数能够接受任意的对象,而你给 test1 的 values 定义的参数中只能包含 name, password, age 这三个属性。
不需要给 test1 中的 values 定义类型 TestData,它会被推断为 Store。 |
18
buffzty 2020-03-03 22:44:18 +08:00
@HanMeiM 为什么去掉形参类型名叫放弃优势呢? 去掉之后什么代码也没多写,类型也自动推断了. 你不就是要这个效果吗 本来能自动推断的,你非要给他加个错误类型
|
19
HanMeiM OP @buffzty 很明显这个 Store 应该是个泛型,只不过他这里写的有问题。你实际写代码的时候,看你代码的人能通过 Store 知道什么呢?我能知道这个表单有哪些数据?这个数据是什么类型?我还是得看上下文代码。
|
20
maichael 2020-03-04 09:16:12 +08:00
@HanMeiM #12
const test1: OnFinishCallback = ((values: TestData) => {}) as OnFinishCallback 一个勉强用着的解决方法。 |
21
LiuJiang 2020-05-17 21:19:15 +08:00
老哥,想问下你们 [email protected] 怎么用 ts 写表单,有代码可以参考下吗,感谢!
|
22
HanMeiM OP @LiuJiang 我个人是这么写的
const handleFinish = (fieldsValue: IFieldsValue) => { ... } <Form onFinish={(value: any) => handleFinish(value)}> ... </Form> |
25
uxstone 2020-07-14 13:53:11 +08:00
Antd V4 文档中的示例代码 TypeScript 和 JavaScript 是一样的
蛋疼,感觉与 TypeScript 整合这块还没有 V3 的好用 |