Тип шрифта a не может быть назначен типу b - PullRequest
1 голос
/ 08 мая 2019

Story

Я использую библиотеку konva с Typescript, который является фреймворком HTML5 Canvas JavaScript.

Вот простой учебный код, который я изменил с 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);

Но мой код 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)

Класс Shape находится в Shape.d.ts и Rectнаходится в Rect.d.ts.И я вижу, что Rect расширен Shape!но VSC выдает ошибку.

Если я добавлю два свойства из 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
    ...
    ...

Вопрос

Я знаю, что layer.add() функция принимает только Shape тип.Но, как вы знаете, 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

Я не могу понять, почему layer.add() не может принять Rect тип, даже если он расширен Shape типом.Что я пропустил?

Мне нужен твой совет.Спасибо.

1 Ответ

2 голосов
/ 08 мая 2019

Определения для библиотеки, по-видимому, не проверены с strictFunctionTypes, к сожалению.

Если эта опция не активирована, функции соотносятся бивариантно, но при strictFunctionTypes функции соотносительно соотносятся с типами параметров. Это значит:

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

Ошибка, которую вы получаете: hitFunc (и если она зафиксирована на sceneFunc), это функции, которые принимают второй параметр this, в действительности Shape<ShapeConfig>. И это вызывает ошибку, когда мы пытаемся присвоить hitFunc в Rect, который принимает второй параметр, также типизированный как this, но в действительности Rect. Вы не можете назначить функцию с производным типом параметра сигнатуре функции, которая будет принимать любой аргумент базового типа.

Существует несколько возможных решений:

  1. Используйте утверждение типа

    layer.add(box as unknown as Shape<ShapeConfig>);
    
  2. Отключить strictFunctionTypes (ошибка исчезает с strictFunctionTypes: false в tsconfig)

  3. Отправьте запрос на выборку для однозначно набранного, чтобы заставить hitFunc и sceneFunc вести себя двумерно, вести себя при strictFunctionTypes: true, как описано здесь . В этом случае это будет работать и сохранить функциональность:

    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>;
    }
    
...