typescript - 打字稿:具有键类型的对象受同一对象的其他键限制
问题描述
好的,所以我有这个函数应该从一个对象接收一个键和一个值。不同的键具有与之关联的不同值类型。
我不想有一个通用功能,如:
function updateField(key: string, value: any) {
}
举个例子,我在这里有这个对象:
interface ISessionSpecific {
students?: number[];
subject?: number;
address?: string;
duration?: string[];
date?: Date;
}
我想创建一个更新此对象中的字段的函数,但我希望它正确键入...
所以当我打电话时:
const value = something;
updateField('address', value);
如果value不是string类型,它将引发错误;
我试过的:
// First Approach:
type ForField<T extends keyof ISessionSpecific> = {
field: T;
value: Required<ISessionSpecific>[T];
};
type Approach1 =
| ForField<'address'>
| ForField<'students'>
| ForField<'date'>
| ForField<'duration'>
| ForField<'subject'>;
// Second Approach
type Approach2<T extends ISessionSpecific = ISessionSpecific> = {
field: keyof T;
value: T[keyof T];
};
// Testing
const x: [Approach1, Approach2] = [
{ field: 'address', value: 0 }, // Error
{ field: 'address', value: 0 }, // No Error
];
我的第一种方法解决了我的问题,但我认为它太冗长了。因为我创建的这个界面只是一个例子……实际的界面可能要大得多。所以我想知道是否有任何更优雅的方法来做到这一点
解决方案
您可以利用分布式条件类型来获取类似于Approach1
自动生成的类型:
type MapToFieldValue<T, K = keyof T> = K extends keyof T ? { field: K, value: T[K] } : never;
const foo: MapToFieldValue<ISessionSpecific> = { field: 'address', value: 0 } // Expect error;
的结果MapToFieldValue<ISessionSpecific>
将是联合等价于:
type ManualMap = {
field: "students";
value: number[] | undefined;
} | {
field: "subject";
value: number | undefined;
} | {
field: "address";
value: string | undefined;
} | {
field: "duration";
value: string[] | undefined;
} | {
field: 'date';
value: Date | undefined;
}
另一种使用映射类型的方法产生相同的结果(感谢@Titian):
type MapToFieldValue<T> = { [K in keyof T]: { field: K, value: T[K] } }[keyof T]