[英]How can I return a NonNullable type in Typescript?
我有类似于以下的代码:
interface Stuff {
foo: number | null;
bar: string | null;
}
let stuff: Stuff;
function getStuff(): Stuff;
function getStuff<K extends keyof Stuff>(key: K): NonNullable<Stuff[K]>;
function getStuff<K extends keyof Stuff>(key?: K): Stuff | NonNullable<Stuff[K]> {
if (key == null)
return stuff;
const value = stuff[key];
if (value == null)
throw new Error(`${key} is null`);
return value;
}
const myStuff = getStuff('foo');
显然,当你到达getStuff
的最后一行时, getStuff
value
不能为null
或undefined
,但 Typescript 给出了这个错误:
Type 'Stuff[K]' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
Type 'string | number | null' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
Type 'null' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
Type 'Stuff[K]' is not assignable to type 'Stuff'.
Type 'string | number | null' is not assignable to type 'Stuff'.
Type 'null' is not assignable to type 'Stuff'.(2322)
如果我删除NonNullable
,那么它可以正常工作,但当然myStuff
将需要一个空检查,这是我在这里试图避免的。 即我知道这里的value
不能为null
,但是我如何正确地让 Typescript 知道,没有“作弊”,例如通过return value!
?
最终将以下 util 添加到我们的项目中,带有断言和辅助类型(因此我们可以在代码中编写Null
而不是null | undefined
一堆地方)
// util/null
type Null = null | undefined;
export default Null;
export function isNotNull<T>(value: T)
: value is NonNullable<T> {
return value != null;
}
export function assertNotNull<T>(value: T, throwError: (value: T) => never)
: asserts value is NonNullable<T> {
if (value == null) throwError(value);
}
您可以简单地进行类型断言 - return value as NonNullable<Stuff[K]>
,或者引入自定义类型保护。
您面临的问题是 TS 没有将您的控制流空检查范围缩小到NonNullable
,但是通过自定义类型保护您可以强制执行它。 考虑:
// type guard narrows to NonNullable
function isNonNullable<T>(a: T): a is NonNullable<T> {
return a !== null
}
function getStuff(): Stuff;
function getStuff<K extends keyof Stuff>(key: K): NonNullable<Stuff[K]>;
function getStuff<K extends keyof Stuff>(key?: K): Stuff | NonNullable<Stuff[K]> {
if (key == null)
return stuff;
const value = stuff[key];
if (isNonNullable(value)) {
return value;
}
throw new Error(`${key} is null`);
}
请注意isNonNullable
是通用类型保护,您可以将其与任何其他值一起使用。
反向条件也将正常工作:
if (!isNonNullable(value)) {
throw new Error(`${key} is null`);
}
return value;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.