打字稿:“关注”条件类型
Posted
技术标签:
【中文标题】打字稿:“关注”条件类型【英文标题】:Typescript: 'Follow' conditional type 【发布时间】:2020-06-25 11:38:20 【问题描述】:Typescript 有什么方法可以推断出b
也属于U extends Foo ? string : number
类型?如果a
是U extends Foo ? string : number
类型,那么在真正的分支中向字符串添加一个数字将导致字符串。在 false 分支中,将一个数字添加到 number 最终将成为一个数字。因此,我希望b
的类型也可以推断为U extends Foo ? string : number
。或者这是一个错误的假设?
当我运行下面的 sn-p 时,出现以下错误:
运算符 '+' 不能应用于类型 'U extends Foo ?字符串:数字'和'数字'。(2365)
interface Foo
propA: boolean;
propB: boolean;
declare function f<T>(x: T): T extends Foo ? string : number;
function foo<U>(x: U, d: number)
const a = f(x);
const b = a + 2;
Playground Link
【问题讨论】:
错误是告诉你不应该在字符串中添加数字。 您可以在字符串中添加数字。这会产生一个字符串。 Typescript 对此没有任何问题:Playground Link 不使用工会:function add(s: string | number) return s + 1; // Error
a
是条件类型,不是联合类型
只是不要 - dev.to/macsikora/this-is-why-typescript-restricts-operator-i0f
【参考方案1】:
Typescript 在这里报错不是因为 javascript 代码在运行时会失败,而是因为根据类型注释,这段代码有时会进行字符串连接,有时会进行算术运算,这通常意味着程序员犯了错误。
当你写+
时,你几乎总是打算要么它意味着字符串连接,要么你打算它意味着算术,但你很少打算它可能意味着两者。因此,这是一个警告代码可能错误的错误。
如果你真的想要一个+
,它有时会进行字符串连接,有时会进行算术运算,你可以在该行之前添加一个@ts-ignore
注释。这类似于Java中的@SuppressWarnings
;您是在告诉编译器不要警告您通常表明错误的事情,因为在这种情况下这不是错误,您不需要编译器警告您。
function foo<U>(x: U, d: number)
const a = f(x);
// @ts-ignore
const b = a + 2;
【讨论】:
a as any
也很丑,但至少是语言结构
写a as any
有什么实际好处吗?类型断言通常应用于 Typescript 不知道正确类型的情况(通常当它推断出比其他推理可能更弱的类型时)并且程序员知道正确的类型。在这种情况下,Typescript确实知道a
的正确类型,所以程序员和编译器不会就它的类型产生分歧,他们不同意“有时连接,有时做算术”是否是一个错误.所以我会在这里使用@ts-ignore
,因为它更符合否决编译器的原因。【参考方案2】:
该问题与 TS 中 +
运算符的严格行为有关。 TS 绝不允许在结果可能超过主要类型string
或主要类型number
的情况下使用+
。函数foo
以这样的方式使用+
,结果类型是联合string | number
,因为函数是多态的,如果参数x
扩展Foo
,那么如果不是@,我们将得到string
987654332@。
在f
级别呈现的条件类型不会评估为foo
中的最终类型,不是,因为我们在此级别有类型变量U
。如果在下面的示例中明确给出类型,它将被评估为特定类型:
// types provided directly
const x = f(1) // number
const y = f(propA: true, propB: false) // string
function inside<U>(a:U)
const x = f(a) // T extends Foo ? string : number // not evaluated
return x + 1; // error
function insideButExactBranch<U extends Foo>(a:U)
const x = f(a)
return x + 1; // ok no error
在foo
中,我们仍然使用未知的U
,这就是为什么f
的结果被认为是任何可能的,这意味着-string | number
。如果是这样,+
将无法编译。
换句话说-TS无法评估f
函数的结果,因此它从条件类型中获取所有可能的返回类型,这意味着联合string | number
。更多关于为什么在 TS 中使用 +
受到限制 - Why TypeScript restricts + operator
【讨论】:
以上是关于打字稿:“关注”条件类型的主要内容,如果未能解决你的问题,请参考以下文章