[Class实现类时接口的Typescript错误类型推断

问题描述 投票:1回答:1

[当在打字稿中使用组合方法而不是继承时,我想根据它们的“可以”而不是它们的“是”来描述我的实体。为了做到这一点,我需要创建一些复杂的接口,然后为我的类(我使用类是为了不创建手动原型链,并且不破坏我认为在js引擎中存在的一些优化)来实现我的接口。但是,如果无法正确推断方法的类型,则会导致奇怪的行为。相反,当使用对象并声明它们具有相同的接口类型时,一切都会按预期进行。

所以我将VSCode与打字稿3.6.3配合使用。我已经为2D形状创建了接口,该接口应具有将所有法线返回到边缘的方法。然后,我创建实现该接口的类,并期望它需要此方法,并且它应具有相同的返回类型(此部分有效)和相同的参数类型(此参数没有)。参数被推断为任意。我的问题是我不想只为了获得一致的VSCode行为而手工创建原型链。

也在控制台中运行tsc时,对于类方法中的参数“ any”类型和访问不存在的prop时对象方法内部的预期错误,我也会收到相同的错误

interface _IVector2 {
  x: number;
  y: number;
}

interface _IShape2D {
  getNormals: ( v: string ) => _IVector2[];
}

export class Shape2D implements _IShape2D {
  getNormals( v ) {
    console.log( v.g );
                   ^ ----- no error here

    return [{} as _IVector2];
  }
}

export const Test: _IShape2D = {
  getNormals( v ) {
    console.log( v.g );
                   ^------ here we get expected error that  
                   ^------ 'g doesn`t exist on type string'

    return [{} as _IVector2];
  }
};

我的tsconfig.json

{
  "compilerOptions": {
    "target": "es2017",
    "allowSyntheticDefaultImports": true,
    "checkJs": false,
    "allowJs": true,
    "noEmit": true,
    "baseUrl": ".",
    "moduleResolution": "node",
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noFallthroughCasesInSwitch": true,
    "jsx": "react",
    "module": "commonjs",
    "alwaysStrict": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "noErrorTruncation": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "watch": true,
    "skipLibCheck": true,
    "paths": {
      "@s/*": ["./src/*"],
      "@i/*": ["./src/internal/*"]
    }
  },
  "exclude": [
    "node_modules"
  ]
}

预期:-类方法的参数应推断为字符串实际:-将方法的参数推断为任何

最终我的问题如下:“这种行为在ts中是无法实现的,我应该求助于手写(哦,亲爱的...)原型链和原型的简单对象吗?”

谢谢您!

typescript class methods interface implements
1个回答
0
投票

这是TypeScript中的design limitation。有一个fix attempted,但它与现有的真实世界代码存在一些不良/中断的交互,因此它们为gave up on it

此时的建议是在实现/扩展类中手动注释参数类型;尽管比较烦人,但是这比求助于手写原型链要好。

export class Shape2D implements _IShape2D {
  getNormals(v: string) { // annotate here
    console.log(v.g); // <-- error here as expected
    return [{} as _IVector2];
  }
}

请注意,v的确可以是anyunknown,而getNormals()将是正确的实现:

export class WeirdShape implements _IShape2D {
  getNormals(v: unknown) { // okay
    return [];
  }
}

这是由于method parameter contravariance是类型安全的... WeirdShape仍然是完全有效的_IShape2D。因此,尽管将参数推断为stringnice,但关于它的一般性并没有incorrect

无论如何,希望能有所帮助;祝你好运!

Link to code

© www.soinside.com 2019 - 2024. All rights reserved.