类实现接口时Typescript错误的类型推断 [英] Typescript incorrect type inference when class implements interface

查看:137
本文介绍了类实现接口时Typescript错误的类型推断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When using composition approach in typescript over inheritance one, I want to describe my entities according to what they "can" and not what they "are". In order to do this I need to create some complex interfaces and then for my classes (I use classes in order not to create manual prototype chain and not break some optimizations that I presume exist inside js engines) to implement my interfaces. But this results in strange behavior when type of a method is not inferred correctly. On the contrary, when using objects and declaring them to be of the same interface type everything works as expected.

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

So I`m using VSCode with typescript 3.6.3. I`ve created interface for 2d shape that should have method to return all normals to edges. Then I create class that implements that interface and I expect it to require this method and it should have the same return type (this part works) and also same argument types (this one doesn`t). Parameter gets inferred as any. My problem is that I don`t want to create prototype chain by hand only to get consistent VSCode behavior.

同样在控制台中运行 tsc 时,在访问不存在的prop时,类方法中的参数为"any"类型的参数和对象方法中的预期错误也得到相同的错误

Also when running tsc in console I get the same error for parameter being 'any' type in class method and expected error inside object method when accessing non-existent 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

my 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"
  ]
}

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

Expected:
- class method`s parameter should be inferred as string
Actual:
- method`s parameter is inferred as any

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

Ultimately my question is as follows: "Is this behavior unachievable in ts and I should resort to hand written (oh dear...) prototype chains and simple objects for prototypes?"

提前谢谢!

推荐答案

这是设计限制在TypeScript中.尝试了修复,但是它与现有的现实世界存在一些不良/中断的交互代码,因此他们放弃.

This is a design limitation in TypeScript. There was a fix attempted but it had some bad/breaking interactions with existing real-world code, so they gave up on it.

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

The suggestion at this point is to manually annotate parameter types in implementing/extending classes; this is better than resorting to hand-written prototype chains, despite being more annoying.

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

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

Note that v could indeed be any or unknown and getNormals() would be a correct implementation:

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

这是由于方法参数相反是类型安全的. .. WeirdShape仍然是完全有效的_IShape2D.因此,虽然将参数推断为string,但并没有什么不正确更为笼统.

This is due to method parameter contravariance being type-safe... a WeirdShape is still a perfectly valid _IShape2D. So, while it would be nice for the parameter to be inferred as string, there's nothing incorrect about it being more general.

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

Anyway, hope that helps; good luck!

链接到代码

这篇关于类实现接口时Typescript错误的类型推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆