繁体   English   中英

通用 function 获取具有默认值的可选属性值

[英]Generic function getting optional property value with default value

有一个 object 类型,如下面的X 请注意,所有属性都是可选的,它们的类型不同,并且对于某些属性, null是一个有效值。

type X = {
  a?: number | null;
  b?: string;
  c?: boolean | null;
};

现在,为了方便起见,我想制作一个 function 来获取X的属性值之一。 function 可以接受默认值并在属性缺失时返回它。

我写的function如下:

function get<K extends keyof X>(k: K, x: X, defaultValue: Required<X>[K]): Required<X>[K] {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

因为属性是可选的,所以我使用Required<X>[K]来获取有效的属性类型(不包括undefined )。

我的预期结果是:

// a: number | null = 12345
const a = get('a', {}, 12345);
// b: string = 'bar'
const b = get('b', { b: 'bar' }, '?');
// c: boolean | null = null
const c = get('c', {}, null);

但是我在get function 的返回语句中得到了以下编译器错误。

Type 'Required<X>[K] | (X[K] & ({} | null))' is not assignable to type 'Required<X>[K]'.
  Type 'X[K] & null' is not assignable to type 'Required<X>[K]'.
    Type 'X[K] & null' is not assignable to type 'never'.

我猜 function 中有错误(可能与Required的使用有关),但我无法解决。

谢谢你。

当您测试v !== undefined TypeScript 时,会将v的类型缩小为X[K] & ({} | null) 此交集类型使用交集从值类型中排除未定义。

Required<X>[K]做类似的事情,但实际上有一个极端情况,当属性类型包含undefined时,它不会从K中删除undefined ,但该属性不是可选的:

//number | undefined
type XX = Required<{ o: undefined | number }>['o']

游乐场链接

即使Required<X>[K]X[K] & ({} | null)更宽松(允许X[K] - optional undefined )TypeScript 将无法按照映射类型得出此结论。

最简单的解决方案是定义一个NotUndefined undefined,类似于 TypeScript 从v中排除undefined的方式,我们可以将其用于返回值和defautlValue参数:

type NotUndefined<T> = T & ({} | null)

function get<K extends keyof X>(k: K, x: X, defaultValue: NotUndefined<X[K]>): NotUndefined<X[K]>  {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

游乐场链接

如果该属性是必需的,并且它的类型中显式undefined ,则上面的版本不允许默认值undefined (例如{ d: boolean | null | undefined; } )。

您可以保留原始行为,方法是将defaultValue恢复为Required<X>[K]并将其添加到与NotUndefined<X[K]>的联合中以返回类型:

function get<K extends keyof X>(k: K, x: X, defaultValue: Required<X>[K]): Required<X>[K] | NotUndefined<X[K]>  {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

游乐场链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM