这是否可以在没有限制的情况下限制类型if
通过函数调用never
返回例如undefined
like assert
在打字稿中?
示例代码:
interface Foo { bar(): void }
function getFoo(): Foo | undefined { }
function test() {
const foo = someService.getFoo();
assert(foo);
if (!foo) { // now mandatory because without this foo may be still undefined even if assert protects us from this
return;
}
foo.bar(); // , here foo may be undefined
}
我希望能够写assert
这样我就可以跳过以下内容if (!foo)
条款并有foo
类型仅限于普通Foo
.
这在打字稿中可能吗?
我尝试过添加重载never
对于抛出的类型:
function assertGuard(v: undefined | null | '' | 0 | false): never;
function assertGuard(v: any): void; // i'm not sure which one is captured by TS typesystem here
function assertGuard<T>(v: T | undefined) {
if (v === undefined || v === null || v === '' || v === 0 || v === false) {
throw new AssertionError({message: 'foo'})
}
}
这个可以编译,但是调用assertGuard(foo)
不认识到这一点undefined
它会返回never
所以不限制foo
to Foo
.
我找到了可能的解决方法,但我认为经典assert
更清洁的方法:
function assertResultDefined<T>(v: T|undefined): T | never {
if (v === undefined) {
throw new Error('foo');
}
return v;
}
function die(): never { throw new Error('value expected)}
const foo = assertResultDefined(getFoo()) // foo is Foo, undefined is erased
const foo = getFoo() || die();
// undefined is erased from foo
/ CONS: doesn't play well with types that interpolate to `false` like 0, ''