如何从可选对象参数中获取文字

时间:2019-06-19 12:39:42

标签: typescript typescript-typings literals typescript-generics

我有以下代码:

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)部分对于这个问题并不重要。

1 个答案:

答案 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