我想我理解新TS 2.1 Pick
type的目的,但后来我看到how it was being used in the React type definitions,我不明白:为什么新的`Pick <T,K extends T>`类型允许React的`setState()`中的`K`的子集?
declare class Component<S> {
setState<K extends keyof S>(state: Pick<S, K>, callback?:() => any): void;
state: Readonly<S>;
}
,它允许你这样做:
interface PersonProps {
name: string;
age: number;
}
class Person extends Component<{}, PersonProps> {
test() {
this.setState({ age: 123 });
}
}
这里我的困惑是那keyof S
是{ name, age }
但我叫setState()
只有age
- 为什么它不抱怨失踪name
?
我的第一个想法是因为Pick
是一个索引类型,它并不需要所有的键都存在。说得通。但是,如果我尝试直接分配类型:
const ageState: Pick<PersonProps, keyof PersonProps> = { age: 123 };
它不抱怨缺少name
键:
Type '{ age: number; }' is not assignable to type 'Pick<PersonProps, "name" | "age">'.
Property 'name' is missing in type '{ age: number; }'.
我不明白这一点。它似乎我所做的就是填补S
与S
已分配的类型,它从允许走了子组键到需要所有键。这是一个很大的区别。 Here it is in the Playground。谁能解释这种行为?
*类型'“年龄”'可以说是延伸型'“名” | “age”'。* 啊,我不会猜到,我会认为''name'| “年龄”延长了“年龄”,而不是其他方式。感谢您的解释! – Aaron
不好意思再说一遍,但是现在我明白了这个行为(谢谢!),但我不能真正理解“年龄”是如何超越“年龄”的。 “name”而不是子类型,即使清楚地知道编译器如何看到它。似乎最上面的看起来与表面上相同的接口“{name,age}”和“{age}”相互关联是相反的。你能解释这个基本原理吗? – Aaron
在泛型类型约束中,可能最好将“extends”理解为“是更具体的类型”。考虑'输入AB =“a”| “b”;'和'输入ABC =“a”| “b”| “C”;'。如果你有一个变量'const abc:ABC =“c”;'那么你不能把它分配给一个类型为'AB'的变量,但任何有效的AB类型值都是'ABC'的有效值。由于'AB'是更具体的'ABC'类型,'AB'可以说是* extend *'ABC'。 –