在typescript类中键入推断

Ton*_*ony 10 type-inference typescript

我期待argparam从父类中推断出类型

export abstract class IEngineClas {
  abstract viewer(arg: string): boolean
}

export class MyClass extends IEngineClas {
  viewer(arg) {
    return true
  }
}
Run Code Online (Sandbox Code Playgroud)

但是在实践中编译器抱怨arg具有任何隐式类型.

我也试过接口

export interface IEngine {
  viewer?: (arg: string) => boolean
}

export class MyClass implements IEngine {
  viewer(arg) {
    return true
  }
}
Run Code Online (Sandbox Code Playgroud)

它有同样的问题,编译器思维arg具有任何类型.

为什么类型推断在这里不起作用?我能做些什么让它发挥作用?

Est*_*ask 6

这里没有类型推断.父类或实现的接口不会推断成员类型.arg不是推断, string而是隐含的 any.

只要与父方法兼容,子类就有可能覆盖方法签名.可以将方法定义为 viewer(arg: any) {...}.由于string是的一个子集any,,这将是允许的,而viewer(arg: boolean) {...}不会.

viewer(arg) {...}结果是隐含anyarg,它与...相同viewer(arg: any) {...}.它将在松散的编译器模式下工作,但会导致类型错误strictnoImplicitAny编译器选项.noImplicitAny 特别有助于避免any在像这样的情况下意外推断.


arv*_*tal 5

当然可以推断! Typescript具有有史以来功能最强大的通用系统!
它只需要一些神秘的语法。

您可以这样写(在Typescript Playground上检查一下):

export abstract class IEngineClas {
  abstract viewer(arg: string): boolean
}

export class MyClass extends IEngineClas {
  viewer(arg: IEngineClas["viewer"] extends (arg: infer U) => any ? U : any) {
    return true
  }
}

let test = (new MyClass()).viewer("hop") // Type OK
let test2 = (new MyClass()).viewer(1)    // Wrong type
Run Code Online (Sandbox Code Playgroud)

说明:

IEngineClas["viewer"] 可以检索父函数的类型: (arg:string) => boolean

使用条件类型,您可以通过使用infer关键字将其分配给泛型来检索所需的arg 。

像这样阅读:如果类型IEngineClas["viewer"](arg: U) => any(带有参数的函数),请抓住U(第一个参数)的类型并将其用作参数的类型arg。否则,请使用type any

编辑

一种更好的编写类型的方法请在Typescript Playground上进行检查):

type firstArg<T> = T extends (arg: infer U) => any ? U : any

export abstract class IEngineClas {
  abstract viewer(arg: string): boolean
}

export class MyClass extends IEngineClas {
  viewer(arg: firstArg<IEngineClas["viewer"]>) {
    return true
  }
}

let test = (new MyClass()).viewer("hop") // Type OK
let test2 = (new MyClass()).viewer(1)    // Wrong type
Run Code Online (Sandbox Code Playgroud)

原因

在另一种情况下,我有一天问为什么与抽象类有关的这些预期推断行为不是默认行为,并回答这是由于性能问题引起的。我承认在大型项目中,Typescript变得非常慢。即使在抽象类上激活或不激活键入的编译标志也将受到欢迎。

我问过的帖子:https : //github.com/Microsoft/TypeScript/issues/21428

一只手...

如果只想消除隐式的任何警告,只需any显式指定类型:viewer(arg:any),或在编译器选项中禁用noImplicitAny标志。