[英]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.