Aar*_*all 6 typescript reactjs typescript2.1
我以为我理解了新的TS 2.1 Pick类型的目的,但后来我看到它是如何在React类型定义中使用的,我不明白:
declare class Component<S> {
setState<K extends keyof S>(state: Pick<S, K>, callback?: () => any): void;
state: Readonly<S>;
}
Run Code Online (Sandbox Code Playgroud)
这允许你这样做:
interface PersonProps {
name: string;
age: number;
}
class Person extends Component<{}, PersonProps> {
test() {
this.setState({ age: 123 });
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我的困惑是,keyof S是{ name, age },但我打电话setState(),只有age-为什么没有抱怨缺少的name?
我的第一个想法是因为Pick是索引类型,它根本不需要存在所有键.说得通.但是,如果我尝试直接分配类型:
const ageState: Pick<PersonProps, keyof PersonProps> = { age: 123 };
Run Code Online (Sandbox Code Playgroud)
它确实抱怨丢失的name密钥:
Type '{ age: number; }' is not assignable to type 'Pick<PersonProps, "name" | "age">'.
Property 'name' is missing in type '{ age: number; }'.
Run Code Online (Sandbox Code Playgroud)
我不明白这一点.这似乎是我所做的就是填补S与该类型S已经被分配给和它允许去子组键来要求所有的钥匙.这是一个很大的不同.这是在游乐场.谁能解释这种行为?
简短回答:如果你真的想要一个显式类型,你可以使用Pick<PersonProps, "age">,但更容易使用隐式类型.
答案很长:
关键点在于它K是一个扩展 的泛型类型变量keyof T.
类型keyof PersonProps等于字符串union "name" | "age".该类型"age"可以说是扩展类型"name" | "age".
回想一下定义Pick是:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
Run Code Online (Sandbox Code Playgroud)
这意味着对于每个K,通过这种类型的描述的对象必须有一个属性P相同的类型属性的K在T.您的示例游乐场代码是:
const person: Pick<PersonProps, keyof PersonProps> = { age: 123 };
Run Code Online (Sandbox Code Playgroud)
展开泛型类型变量,我们得到:
Pick<T, K extends keyof T>,Pick<PersonProps, "name" | "age">,[P in "name" | "age"]: PersonProps[P],最后{name: string, age: number}.当然,这与...不相容{ age: 123 }.如果你改为说:
const person: Pick<PersonProps, "age"> = { age: 123 };
Run Code Online (Sandbox Code Playgroud)
然后,按照相同的逻辑,person将适当的类型相当于{age: number}.
当然,TypeScript无论如何都会为你计算所有这些类型 - 这就是你得到错误的方法.由于TypeScript已经知道类型{age: number}并且Pick<PersonProps, "age">兼容,因此您可以保持类型impicit:
const person = { age: 123 };
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
652 次 |
| 最近记录: |