TypeScript 在类中声明属性或方法时,关于协变性的不同行为

eanckbw9  于 6个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(53)

TypeScript版本: 4.1.2
搜索关键词: 在ts doc中,似乎没有提到关于类型兼容性的内容。
代码

class M1 {
  c: number = 1;
}

export class M2 extends M1 {
  a: number = 1;
}

type Func<M extends M1> = (m: M) => number;

interface IFunc<M extends M1> {
  func1?: Func<M>,
  func2: Func<M>,
}

class R1<M extends M1 = M1> implements IFunc<M> {
  // when delete this property, it will be no error.
  public func1 = (m: M) => {
    return m.c
  }

  public func2(m: M) {
    return m.c
  };
}

type IRConstructor<M extends M1, R extends R1<M>> = new () => R;

export class R2 extends R1<M2> {
}

type A = IRConstructor<M1, R1>;

let a1: A = R2; // error: Type 'typeof R2' is not assignable to type 'IRConstructor<M1, R1<M1>>'.

console.log(a1);

预期行为:

在类中声明具有相同行为的属性或方法?我不确定...实际上我想了解如何在使用函数属性时使这些代码不报错。

实际行为:

当你只是声明一个与IFunc<M1>兼容的方法时,它会很好。但是当你声明一个与IFunc<M1>兼容的函数属性时,它会报错。

** playground链接:**

或者,你可以查看playground

相关问题:

wvt8vs2t

wvt8vs2t1#

或者,如果可以像Objective-C的__kindof那样手动添加一个关键字来忽略协变性问题呢?
当有人想要忽略这些问题时,他们唯一能做的就是将strictFunctionTypes标志设置为false。但是整个项目都会受到这个标志的影响。我能否只是忽略这一行的类型检查,而不使用类型转换或@ts-ignore呢?

mrfwxfqh

mrfwxfqh2#

我们需要在文档中提到这一点,是的,方法会双向检查,但属性会使用正确的可变性进行检查。您可以禁用 strictFunctionTypes 以使所有函数参数双向检查。

ni65a41a

ni65a41a3#

我们需要在文档中提到这一点,是的,方法会双向检查,但属性会使用正确的协变性进行检查。你可以禁用 strictFunctionTypes 来让所有函数参数双向检查
感谢你的回复。是的,我可以禁用 strictFunctionTypes 标志来解决这个问题,但这意味着项目的所有函数参数都会双向检查。
所以...如果有可能添加一个新的关键字(或其他方式)仅使函数参数仅对一个方法(或单个文件)进行双向检查......?就像 Objective-C 中的 __kindof 关键字一样。
例如,当你编写这样的代码时:

@interface TestInterface
  @property(nonatomic) NSArray<__kindof UIView *> *array;
@end

这意味着 TestInterface 中有数组,该数组中的所有成员都可以是 UIView或 UIView 的某个子类
在我的情况下,我只想让 func1 属性知道输入参数可以是 M1M1 的某个子类,并且该属性可以通过 (m: M2) => numberR2 覆盖,而不是让所有函数参数双向检查。我想要的是像这样:

class M1 {
  c: number = 1;
}

export class M2 extends M1 {
  a: number = 1;
}

class R1 {
  public func1 = (m: __kindof M1) => {
    return m.c;
  };
}

export class R2 extends R1 {
  public func1 = (m: M2) => { // no error
    return m.c;
  };
}
nsc4cvqm

nsc4cvqm4#

我们需要在文档中提到这一点,是的,方法会双向检查,但属性会使用正确的可变性进行检查。你可以禁用 strictFunctionTypes 以使所有函数参数双向检查
以下问题是否相同?
strictFunctionTypes 为真时,我希望编译器将属性和方法定义视为相同。或者我们需要一个 stricterFunctionTypes 吗?😄

type Func<P> = (p: P) => void

let a!: Func<{ a: number }>
let b!: Func<{ a: number; b: number }>

a = b // Correctly flagged as error
b = a

interface Wrapped<P> {
  func(p: P): void
  // Replace with the following, then it correctly flags an error below
  // func: Func<P>
}

let c!: Wrapped<{ a: number }>
let d!: Wrapped<{ a: number; b: number }>

a = d.func // Correctly flagged as error
b = c.func

c.func = d.func // Not flagged as error!
d.func = c.func

相关问题