简体   繁体   English

打字稿类型a不可分配给类型b

[英]Typescript type a is not assignable to type b

Story 故事

I'm using konva library with Typescript which is HTML5 Canvas JavaScript framework. 我正在使用带有Typescript的konva库 ,它是HTML5 Canvas JavaScript框架。

Here is a simple tutorial code that I changed from javascript to typescript. 这是一个简单的教程代码,我从javascript更改为打字稿。

import Konva from "konva";

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight
});

const layer = new Konva.Layer();
stage.add(layer);

const box = new Konva.Rect({
  x: 50,
  y: 50,
  width: 100,
  height: 50,
  fill: '#00D2FF',
  stroke: 'black',
  strockWidth: 4,
  draggable: true
});

layer.add(box);

But my Visual Studio Code shows error message like below. 但是我的Visual Studio代码显示如下错误消息。

Argument of type 'Rect' is not assignable to parameter of type 'Group | Shape<ShapeConfig>'.
  Type 'Rect' is not assignable to type 'Shape<ShapeConfig>'.
    Types of property 'hitFunc' are incompatible.
      Type 'GetSet<(ctx: Context, shape: Rect) => void, Rect>' is not assignable to type 'GetSet<(ctx: Context, shape: Shape<ShapeConfig>) => void, Shape<ShapeConfig>>'.
        Type '(ctx: Context, shape: Rect) => void' is not assignable to type '(ctx: Context, shape: Shape<ShapeConfig>) => void'.
          Types of parameters 'shape' and 'shape' are incompatible.
            Type 'Shape<ShapeConfig>' is missing the following properties from type 'Rect': _sceneFunc, cornerRadiusts(2345)

The class Shape is in Shape.d.ts and Rect is in Rect.d.ts . Shape类在Shape.d.tsRectRect.d.ts And I can see that Rect extended Shape ! 我可以看到Rect扩展了Shape but VSC shows an error. 但VSC显示错误。

If I add the two property which is in Rect.d.ts to Shape class, the error is gone . 如果我将Rect.d.ts的两个属性添加到Shape类, 则错误消失了

export declare class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<Config> {
    _sceneFunc(context: any): void; // this was in Rect class
    cornerRadius: GetSet<number, this>; // this was in Rect class
    ...
    ...

Question

I know that layer.add() function accept only Shape type. 我知道layer.add()函数仅接受Shape类型。 But as you know Typescript allows downcasting like below. 但是,您知道Typescript允许向下转换,如下所示。

class Base {
  baseProperty: string = "aaaa";
}
class A extends Base {
  aProperty: number = 1;
}
var a: A = new A();
function test(arg: Base) {
  console.log(arg.baseProperty);
}
test(a); // => No Error

I cannot understand why layer.add() cannot accept Rect type even though it extended Shape type. 我不明白为什么layer.add()不能接受Rect类型,即使它扩展了Shape类型。 What did I miss? 我错过了什么?

I need your advice. 我需要你的建议。 Thanks. 谢谢。

The definitions for the library are apparently not tested with strictFunctionTypes unfortunately. 不幸的是,该库的定义显然未经过strictFunctionTypes测试。

If this option is not activated, functions relate bivariantly, but under strictFunctionTypes functions relate contravariantly with regard to parameter types. 如果未激活此选项,则函数是双变量的,但是在strictFunctionTypes下,函数在参数类型方面是strictFunctionTypes变量的。 This means: 这意味着:

class Animal { private x:undefined }
class Dog extends Animal { private d: undefined }

type EventHandler<E extends Animal> = (event: E) => void

let o: EventHandler<Animal> = (o: Dog) => { } // fails under strictFunctionTyes

The error you are getting is on hitFunc (and if that is fixed on sceneFunc ) these are functions that take a second parameter of this , in effect Shape<ShapeConfig> . 您遇到的错误是在hitFunc (并且如果在sceneFunc上已sceneFunc ),这些函数采用this函数的第二个参数,实际上是Shape<ShapeConfig> And this triggers the error when we try to assign the hitFunc in Rect that has takes a second parameter, also typed as this but in effect Rect . 当我们尝试在具有第二个参数的Rect中分配hitFunc时,这会触发错误,该参数也被键入为this但实际上是Rect You can't assign the function with the derived parameter type to a function signature that would accept any base type argument. 您不能将具有派生参数类型的函数分配给可以接受任何基本类型参​​数的函数签名。

There are multiple possible solution: 有多种可能的解决方案:

  1. Use a type assertion 使用类型断言

     layer.add(box as unknown as Shape<ShapeConfig>); 
  2. Disable strictFunctionTypes (the error goes away with strictFunctionTypes: false in tsconfig) 禁用strictFunctionTypes (该错误随strictFunctionTypes: false

  3. Submit a pull request to definitely typed to make hitFunc and sceneFunc behave bivariantly event under strictFunctionTypes: true as described here . 提交pull请求,肯定类型做出hitFuncsceneFunc表现下bivariantly事件strictFunctionTypes: true的描述在这里 In this case this would work and preserve the functionality: 在这种情况下,它将起作用并保留功能:

     export type ShapeConfigHanlder<TTarget> = { bivarianceHack(ctx: Context, shape: TTarget): void }['bivarianceHack'] export interface Shape extends NodeConfig { ... hitFunc: GetSet<ShapeConfigHanlder<this>, this>; sceneFunc: GetSet<ShapeConfigHanlder<this>, this>; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM