🔍 搜索词
unknown, assert, narrow, undefined, "is not"
✅ 可实现性检查清单
- 这不会对现有的TypeScript/JavaScript代码造成破坏性的改变
- 这不会改变现有JavaScript代码的运行时行为
- 这可以在不根据表达式的类型发射不同的JS的情况下实现
- 这不是一个运行时特性(例如库功能、带有JavaScript输出的非ECMAScript语法、新的JS语法糖等)
- 这个特性将与我们设计目标的其他部分一致: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ 建议
这看起来像是之前被问过的问题,但很难搜索到。
目前 asserts
是一个非常神奇的语法,可以让你做:
function assert(proposition: unknown): asserts proposition {
if (!proposition) {
throw new Error()
}
}
function foo(value: unknown): {} | null {
assert(value !== undefined);
return value;
}
然而,尝试表达更专业的函数是行不通的。
function assertNotUndefined<T>(value: T): asserts value is Exclude<T, undefined> {
if (value === undefined) {
throw new Error();
}
}
function foo(value: unknown): {} | null {
assertNotUndefined(value);
return value; // Doesn't work
}
这是因为 Exclude<unknown, undefined>
仍然只是 unknown
,因为 unknown
不是 {} | null | undefined
的别名。假设这一点不会改变,那么如何表达 assertNotUndefined
呢?好吧,如果我们拿原来的 assert
函数并试着将其语法理性化为这个
function assert(proposition: unknown): asserts proposition;
当作为
assert(proposition !== undefined)
(手势)时,只特化为这个
function assert(proposition: unknown): asserts proposition !== undefined;
我不关心是否应该使用 asserts proposition is not undefined
作为语法,操作数的左侧或右侧是否可以翻转,是否应该存在 !=
或其他运算符,或者除了像 undefined
这样的基本字面量之外的其他类型表达式是否应该被支持,所以我把它留给评论。
📃 激励示例
function assertNotUndefined(proposition: unknown): asserts proposition !== undefined;
function foo(value: unknown): {} | null {
assertNotUndefined(value);
return value; // Works!
}
💻 用例
- 你打算用这个做什么?
一个可以排除undefined
的函数可以与其他函数组合,例如array.filter(isNotUndefined)
- 目前方法存在的缺点是什么?
没有干净的方法来定义这样一个函数,而不需要丑陋的条件语句来处理unknown
。 - 在这段时间里你正在使用什么解决方法?
以更冗长的风格重写代码,例如手动使用for
循环构造一个新的数组而不是array.filter
。
3条答案
按热度按时间eyh26e7m1#
这个怎么样?
似乎可以正常工作,因为
unknown
可以分配给{} | null | undefined
。332nm8kg2#
这个怎么样?
似乎可以正常工作,因为
unknown
可以分配给{} | null | undefined
。我认为这是一个足够解决这个问题的方案,我很可能最终会使用它 :)。
一般来说,我尽量将参数类型视为一个通用类型参数,而不是从类型参数派生的类型,因为我学到了不要相信TS能够为任何非平凡的类型推断出正确的类型参数的能力。我觉得当TS可以从用法中推断出正确的类型参数时和无法推断出正确类型参数时,情况描述不够明确,这是我不想依赖的东西。
brgchamk3#
在一般情况下,你可能需要 #4196 来实现这个功能。
至于 TS 无法推断类型,这通常是因为类型系统是结构性的,所以当你的推断站点是
DerivedFrom<T>
时,编译器必须从派生类型向后推理T
。如果推导是损失性的,甚至可能无法可靠地从它中恢复T
。