[英]How can I return a NonNullable type in Typescript?
I have code similar to the following:我有类似于以下的代码:
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');
Clearly, when you get to the last line of getStuff
, value
cannot be null
or undefined
there, but Typescript gives this error:显然,当你到达
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)
If I remove NonNullable
, then it works correctly, but of course myStuff
will then require a null check instead, which is what I'm trying to avoid here.如果我删除
NonNullable
,那么它可以正常工作,但当然myStuff
将需要一个空检查,这是我在这里试图避免的。 Ie I know value
cannot be null
here, but how do I properly let Typescript know that, without "cheating", eg via return value!
即我知道这里的
value
不能为null
,但是我如何正确地让 Typescript 知道,没有“作弊”,例如通过return value!
? ?
Ended up adding the following util to our project, with the assertions and a helper type (so we can write Null
instead of null | undefined
a bunch of places in our code)最终将以下 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);
}
You can just simply do type assertion - return value as NonNullable<Stuff[K]>
, or introduce the custom type guard.您可以简单地进行类型断言 -
return value as NonNullable<Stuff[K]>
,或者引入自定义类型保护。
The issue you are facing is that TS is not narrowing your control flow null check to NonNullable
, but by custom type guard you can force it.您面临的问题是 TS 没有将您的控制流空检查范围缩小到
NonNullable
,但是通过自定义类型保护您可以强制执行它。 Consider:考虑:
// 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`);
}
Pay attention that isNonNullable
is generic type-guard which you can use with any other value.请注意
isNonNullable
是通用类型保护,您可以将其与任何其他值一起使用。
Reversed condition will also work correctly:反向条件也将正常工作:
if (!isNonNullable(value)) {
throw new Error(`${key} is null`);
}
return value;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.