type Assignable<T, U> = T extends U ? true : false
type Father = (a: Record<string, any>) => void
type Son = (a: { count: number }) => void
type R1 = Assignable<Son, Father> // false
type R2 = Assignable<Father, Son> // true
type R3 = Assignable<Parameters<Son>, Parameters<Father>> // true
type R4 = Assignable<{ count: number }, Record<string, any>> // true
{ count: number }
可以赋给( TypeScript 官方叫它 assignable )类型Record<string, any>
我能理解没问题,
但为什么放到函数的参数里就反过来了呢?
Son 不应该也是 Father 的子类型
吗?
附上 playgorund: https://reurl.cc/12nVGV
我的逻辑思维可能太差了💀
提前感谢点开此贴🙏
1
noe132 2022-04-14 16:01:58 +08:00 via Android 2
这是 Covariance and contravariance 的区别。
比如我们说 dog extends animal 如果一个函数调用接受一个 animal ,那么你传 dog 是没有问题的。 但是如果一个函数调用接受一个 callback ,这个 callback 会收到一个 animal ,如果你传一个收到 dog 的 callback 就不行。因为 callback 的调用方有可能会给你一个 animal ,但 animal 不是 dog 。 针对类型 T ,如果说 T<dog> extends T<animal> 则 T 是 covarient 。如果 T<animal> extends T<dog>,则 T 是 contravariant 。在你这个例子里,T = (v: T) => void |
2
noe132 2022-04-14 16:04:03 +08:00 via Android
最后一句有些错误,应该是:在你这个例子里,type T<U> = (v: U) => void
|
3
noe132 2022-04-14 16:09:49 +08:00 via Android 1
还有一些比较特殊的例子是 invarient 的。最常见的就是可写数组。因为数组的读操作是 corarient ,而写是 contravarient ,2 者结合起来就是 invarient 。
Array<Dog> 可以 push 一个 GrayHound 进去,也可以 pop 一个 animal 出来,但是不能赋值给 Array<Animal> 或者 Array<GrayHound> 的变量,因为前者可能会 push 一个 dog 进去,后者可能会 pop 一个 dog 出来。 |
4
chenluo0429 2022-04-14 16:18:30 +08:00 via Android 1
举个栗子:
Farther 类型对应的是可以给所有动物洗澡的机器,参数是所有动物。 Son 类型是可以给狗洗澡的机器,参数是狗。 如果你需要一个动物,我可以给你只狗。 如果你需要一台可以给狗洗澡的机器,我可以给你一台能给所有动物洗澡的机器,但是反过来就不对了。 |
5
enchilada2020 2022-04-14 18:13:52 +08:00 via Android 2
|
6
johnkiller OP |