Ric*_*ick 16 interface typescript
假设我有一个界面:
interface IUser {
email: string;
id: number;
phone: string;
};
Run Code Online (Sandbox Code Playgroud)
然后我有一个期望该类型的子集(或完全匹配)的函数.也许它会通过一个完整的物体,使它只会传入{email: "t@g.com"}.我希望类型检查器允许两者.
例:
function updateUser(user: IUser) {
// Update a "subset" of user attributes:
$http.put("/users/update", user);
}
Run Code Online (Sandbox Code Playgroud)
Typescript是否支持这种行为呢?我觉得它非常有用,特别是像Redux这样的范例.
澄清一下,目标是:
if语句,这会失去编译时类型检查的好处.更新: Typescript宣布支持映射类型,一旦发布就应该解决这个问题.
Ric*_*ick 32
Typescript现在支持部分类型.
创建部分类型的正确方法是:
type PartialUser = Partial<IUser>;
Run Code Online (Sandbox Code Playgroud)
你想要的是这个
type Subset<T extends U, U> = U;
Run Code Online (Sandbox Code Playgroud)
这可以确保U是T的子集,并将U作为新类型返回。例如:
interface Foo {
name: string;
age: number;
}
type Bar = Subset<Foo, {
name: string;
}>;
Run Code Online (Sandbox Code Playgroud)
you can not add new properties to Bar which are not part of Foo - and you can not alter types in a non-compatible way. this also works recursively on nested objects.
值得注意的是Partial<T>,正如接受的答案中所建议的那样,使所有字段都是可选的,这不一定是您需要的。
如果您想将某些字段(例如id和email)设为必填字段,则需要将其与结合使用Pick:
type UserWithOptionalPhone = Pick<IUser, 'id' | 'email'> & Partial<IUser>
Run Code Online (Sandbox Code Playgroud)
一些解释:
是什么Pick做的是,它可以让你指定接口的子集简洁(无需创建一个全新的界面重复字段类型,通过其他的答案的建议),然后让你使用那些和只有那些领域。
function hello1(user: Pick<IUser, 'id' | 'email'>) {
}
hello1({email: '@', id: 1}); //OK
hello1({email: '@'}); //Not OK, id missing
hello1({email: '@', id: 1, phone: '123'}); //Not OK, phone not allowed
Run Code Online (Sandbox Code Playgroud)
现在,这并不是我们想要的,我们想要允许,但不需要电话。为此,我们通过创建一个交集类型来 “合并”该类型的部分和“挑选”版本,该交集类型将具有id和email必填字段,而其他所有内容都是可选的-正是我们想要的。
function hello2(user: Pick<IUser, 'id' | 'email'> & Partial<IUser>) {
}
hello2({email: '@', id: 1}); //OK
hello2({email: '@', id: 1, phone: '123'}); //OK
hello2({email: '@'}); //Not OK, id missing
Run Code Online (Sandbox Code Playgroud)
具有映射类型的正确解决方案:
updateUser<K extends keyof IUser>(userData: {[P in K]: IUser[P]}) {
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6506 次 |
| 最近记录: |