我希望有一个具有单个泛型的接口,其中一个属性是keyof T
,另一个是在第一个属性上传递的正确的T[keyof T]
。
以下代码几乎可以满足此要求,正确键入第一个属性(field
):
interface RandomType {
foo: string;
bar: number;
baz: boolean;
}
type Typer<T = Record<string, any>> = {
field: keyof T,
value: T[any]
}
const param: Typer<RandomType> = {
field: 'baz',
value: 'foo'
}
但是,我需要根据value
的值输入field
在上一个示例中,它应该触发类型错误,因为RandomType['baz']
是boolean
答案 0 :(得分:1)
您希望Typer<T>
成为T
中每个字段的字段union。您可以通过多种方式执行此操作。例如:
type Typer<T> = { [K in keyof T]: {
field: K,
value: T[K]
} }[keyof T];
在这里,我们mapping over是T
中的属性,以获取其值是所需类型的新对象,然后立即looking up其所有值。
您可以验证Typer<RandomType>
是您要查找的内容:
type TyperRandomType = Typer<RandomType>
/* type TyperRandomType = {
field: "foo";
value: string;
} | {
field: "bar";
value: number;
} | {
field: "baz";
value: boolean;
} */
然后您的示例给出了您期望的错误:
const param: Typer<RandomType> = {
field: 'baz',
value: 'foo'
}; // error!
// Types of property 'value' are incompatible.
// Type 'string' is not assignable to type 'boolean'
答案 1 :(得分:0)
这可以做您想要的,但是现在您必须两次指定密钥:
type Typer<T, K extends keyof T> = {
field: K,
value: T[K]
}
const param: Typer<RandomType, 'baz'> = {
field: 'baz',
value: 'foo' // Type 'string' is not assignable to type 'boolean'. ts(2322)
}
我认为TS存在一个未解决的问题,使得仅指定某些泛型并推断其余泛型成为可能,以便Typer<RandomType>
可以正常工作。