假设我有一个这样的界面:
interface Cat {
weight: number;
name: string;
adoptable: boolean;
}
Run Code Online (Sandbox Code Playgroud)
我想定义以下可用于设置值的接口Cat:
interface CatUpdate {
field: keyof Cat;
value: ???
}
Run Code Online (Sandbox Code Playgroud)
我希望 TypeScript 强制该值是基于字段的适当类型。例如,这应该是无效的:
const x: CatUpdate = {
field: "name",
value: 12
}
Run Code Online (Sandbox Code Playgroud)
我如何定义类型CatUpdate.value?
我的倾向是创建CatUpdate一个联合类型而不是接口,如下所示:
interface Cat {
weight: number;
name: string;
adoptable: boolean;
}
type PropUpdate<T extends object> = {
[K in keyof T]: { field: K; value: T[K] }
}[keyof T];
type CatUpdate = PropUpdate<Cat>;
/*
type CatUpdate = {
field: "weight";
value: number;
} | {
field: "name";
value: string;
} | {
field: "adoptable";
value: boolean;
}
*/
Run Code Online (Sandbox Code Playgroud)
这对于您提到的用例应该足够有效:
const x: CatUpdate = {
field: "name",
value: 12
} // error!
Run Code Online (Sandbox Code Playgroud)
如果需要,您应该能够组合这些 ( CatUpdate | DogUpdate),尽管没有特定的用例,很难知道这种组合是否合适(可以Cat和Dog相互区分吗?也就是说,Cat & Dog不可能?如果Cat & Dog可能,那么CatUpdate | DogUpdate只能用于更新Cat & Dog。如果不可能,那么CatUpdate | DogUpdate可能应该替换为可区分的联合,而不是像(CatUpdate & {kind: "CatUpdate"}) | (DogUpdate & {kind: "DogUpdate"})。)
希望有帮助;祝你好运!
一种方法是使用泛型类型:
interface CatUpdate<T extends keyof Cat> {
field: T;
value: Cat[T];
}
Run Code Online (Sandbox Code Playgroud)
它可以工作,但这意味着您在创建对象时需要更详细一些。
// Error
const x: CatUpdate<"name"> = {
field: "name",
value: 12
}
// No error
const y: CatUpdate<"name"> = {
field: "name",
value: "Dave"
}
Run Code Online (Sandbox Code Playgroud)
一种解决方案是使用一个函数进行实例化,该函数可以根据参数推断类型:
function getCatUpdate<T extends keyof Cat>(field: T, value: Cat[T]): CatUpdate<T> {
return {
field,
value
}
}
Run Code Online (Sandbox Code Playgroud)
你可以这样称呼:
// Error
const x = getCatUpdate("name", 12);
// No error
const y = getCatUpdate("name", "Dave");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1488 次 |
| 最近记录: |