"pick" 函数的 TypeScript 泛型类型(结果对象值类型)
TypeScript generic type for "pick" function (result object values types)
选择函数的写入类型有问题。仅选择一个键或具有相同类型值的多个键时一切正常。但是如果我试图选择几个键并且它们的值是不同的类型 - 我会得到一个错误。不太确定我哪里弄错了。
感谢您的宝贵时间。
export interface Mapper<T = any, R = any> {
(arg: T): R;
}
export function pick<O, T extends keyof O>(keys: T[], obj?: O): { [K in T]: O[T] };
export function pick<T>(keys: T[], obj?: never): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
const picker: Mapper<O, { [K in T]: O[T] }> = _obj =>
keys.reduce((acc, key) => {
if (key in _obj) {
acc[key] = _obj[key];
}
return acc;
}, {} as O);
return obj ? picker(obj) : picker;
}
const obj = { someKey: 'value', otherKey: 42, moreKey: ['array value'] };
const newObj = pick(['otherKey'], obj);
//OK. TS type for newObj is {otherKey: number}
const n: number = newObj.otherKey;
// OK
const otherNewObj = pick(['otherKey', 'someKey'], obj);
//no really OK. TS type for otherNewObj is {otherKey: number | string, someKey: number | string}
const m: number = otherNewObj.someKey;
// Error. Type string | number is not assignable to the number
您的映射类型有误,您可能想使用 O[K]
而不是 O[T]
,所以您最终得到 { [K in T]: O[K] }
。您需要每个键 K
的类型,而不是 T
联合中所有属性的类型。
另外我会使用 Pick
因为 Pick
是同态的并且会保留修饰符,例如 readonly
和 optional
.
而且 obj?: never
可能不会做你想让它做的事情,任何东西都可以分配给 never
,你最好在重载中省略参数:
export function pick<O, T extends keyof O>(keys: T[], obj?: O): Pick<O, T>;
export function pick<T>(keys: T[]): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
//....
}
选择函数的写入类型有问题。仅选择一个键或具有相同类型值的多个键时一切正常。但是如果我试图选择几个键并且它们的值是不同的类型 - 我会得到一个错误。不太确定我哪里弄错了。
感谢您的宝贵时间。
export interface Mapper<T = any, R = any> {
(arg: T): R;
}
export function pick<O, T extends keyof O>(keys: T[], obj?: O): { [K in T]: O[T] };
export function pick<T>(keys: T[], obj?: never): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
const picker: Mapper<O, { [K in T]: O[T] }> = _obj =>
keys.reduce((acc, key) => {
if (key in _obj) {
acc[key] = _obj[key];
}
return acc;
}, {} as O);
return obj ? picker(obj) : picker;
}
const obj = { someKey: 'value', otherKey: 42, moreKey: ['array value'] };
const newObj = pick(['otherKey'], obj);
//OK. TS type for newObj is {otherKey: number}
const n: number = newObj.otherKey;
// OK
const otherNewObj = pick(['otherKey', 'someKey'], obj);
//no really OK. TS type for otherNewObj is {otherKey: number | string, someKey: number | string}
const m: number = otherNewObj.someKey;
// Error. Type string | number is not assignable to the number
您的映射类型有误,您可能想使用 O[K]
而不是 O[T]
,所以您最终得到 { [K in T]: O[K] }
。您需要每个键 K
的类型,而不是 T
联合中所有属性的类型。
另外我会使用 Pick
因为 Pick
是同态的并且会保留修饰符,例如 readonly
和 optional
.
而且 obj?: never
可能不会做你想让它做的事情,任何东西都可以分配给 never
,你最好在重载中省略参数:
export function pick<O, T extends keyof O>(keys: T[], obj?: O): Pick<O, T>;
export function pick<T>(keys: T[]): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
//....
}