如何基于参数执行动态typescript返回类型尚未定义。请帮忙。
还添加了一个Typescript Playground Snippet以供参考
我已经想出了这个办法,但没有像预期的那样奏效。
V extends keyof T ? ToObject<T> : ToObject<T[keyof T]>
代码:
export interface ToObject<T> {
[k: string]: T;
}
export const toObject = <T, V = (keyof T)>(
list: T[],
key: keyof T,
valueKey?: V
): V extends keyof T ? ToObject<T> : ToObject<T[keyof T]> => valueKey === undefined
? list.reduce((all, cur) => ({
...all,
[cur[key] as unknown as string]: cur
}), {} as ToObject<T>)
: list.reduce((all, cur) => ({
...all,
[cur[key] as unknown as string]: cur[valueKey as unknown as keyof T]
}), {} as ToObject<T[keyof T]>);
用法:
interface Data{
a: string;
b: string;
c: string;
}
const list: Data[] = [
{a:'a', b: 'b', c: 'c'},
{a:'1', b: '2', c: '3'}
];
// use 1
toObject<Data>(list, 'a');
// response
{
{'a': {a:'a', b: 'b', c:'c'}},
{'1': {a:'1', b:'2', c: '2'}},
}
// Use 2
toObject<Data>(list, 'a', 'b');
//response
{ {'a': 'b'}, {'1': '2'} }
问题:
// use 1 ERROR -> Cant do this
const dataMap: ToObject<Data> = toObject<Data>(list, 'a');
// Type 'ToObject<Data> | ToObject<string>' is not assignable to type 'ToObject<Data>'.
// Type 'ToObject<string>' is not assignable to type 'ToObject<Data>'.
// Type 'string' is not assignable to type 'Data'.(2322)
// Use 2 ERROR -> Cant do this
const dataKeyMap: ToObject<string> = toObject<Data>(list, 'a', 'b');
// Type 'ToObject<Data> | ToObject<string>' is not assignable to type 'ToObject<string>'.
// Type 'ToObject<Data>' is not assignable to type 'ToObject<string>'.
// Type 'Data' is not assignable to type 'string'.(2322)
正如所写的,TS没有足够的信息来区分toObject
的两种返回类型。
如果我们添加函数重载,我们可以将返回类型绑定到函数签名。如果CCD_ 2通过,toObject
返回ToObject<T[keyof T]>
,否则函数返回ToObject<T>
。
修订后的游乐场
export function toObject <T, V = (keyof T)>(list: T[], key: keyof T): ToObject<T>
export function toObject <T, V = (keyof T)>(list: T[], key: keyof T, valueKey: V): ToObject<T[keyof T]>
export function toObject <T, V = (keyof T)>(list: T[], key: keyof T, valueKey?: V): ToObject<T> | ToObject<T[keyof T]> {
return valueKey === undefined
? list.reduce((all, cur) => ({
...all,
[cur[key] as unknown as string]: cur
}), {} as ToObject<T>)
: list.reduce((all, cur) => ({
...all,
[cur[key] as unknown as string]: cur[valueKey as unknown as keyof T]
}), {} as ToObject<T[keyof T]>);
}
除了让TS编译器高兴之外,重载还通知用户应该如何调用函数。