我有以下代码:
const dd = ['a', 'b'] as const;
function cba<T extends readonly string[]>(a: { b: T }) {
return (1 as any) as typeof a.b[number];
}
const a = cba({ b: dd });
const b = cba({ b: ['a', 's']});
变量a
返回'a' | 'b'
类型,变量b
返回string
类型,这正是我想要的。有什么方法可以使b
属性成为可选属性,然后如果存在则返回上面的文字,否则返回string
?这是我正在尝试的:
function cba<T extends readonly string[]>(a: { b?: T }) {
return (1 as any) as typeof a.b extends 'undefined' ? string : typeof a.b[number];
}
,但它在typeof a.b[number]
部分返回ts错误,提示信息该数字无法应用于T | undefined
。我也在尝试JS解决方案,以检查b
属性是否存在:
function cba<T extends readonly string[]>(a: { b?: T }) {
const d = a.b;
if (d) return (1 as any) as typeof d[number];
else return (1 as any) as string;
}
,但是它总是返回string | undefined
类型。有什么想法吗?
PS。 (1 as any)
部分对于这个问题并不重要。
答案 0 :(得分:0)
您可以使用条件类型来做到这一点:
type Values<T extends readonly string[] | undefined> =
T extends readonly string[] ? T[number] : undefined;
const dd = ['a', 'b'] as const;
function cba<T extends readonly string[] | undefined>(a: { b?: T }) {
return (1 as unknown) as Values<T>;
}
const a = cba({ b: dd }); // "a" | "b"
const b = cba({ b: ['a', 's']}); // string
const c = cba({}); // string | undefined