当前位置: 首页 > 知识库问答 >
问题:

TypeScript从子类调用的构造函数参数推断类型

邢硕
2023-03-14

我有一个类,它有一些属性/方法,返回最初通过构造函数传递的值:

class Base {
  constructor(arg) {
     this.options = arg.options;
  }
}

人们建议用泛型作为打字稿的等价物:

class Base<T extends {options: any}> {
    options: T["options"];

    constructor(arg: T) {
        this.options = arg.options;
    }    
}

// works fine with instantiation
const inst = new Base({options: {foo: 123}});
inst.options.foo++; // ok
inst.options.bar; // TS Error

现在我有了一个子类,它调用超类的构造函数并传递以下选项:

class Sub extends Base { // TS Error
    constructor() {
        super({options: {foo: 123}});
        this.options.foo++; // TS Error
    }
}

TypeScript编译器对此不满意,希望通过类型扩展Base类。但是我有两次信息,在超级呼叫和扩展符号中。什么是正确的ts语法来解决我的问题?

(键入脚本中的代码)

共有1个答案

禄仲渊
2023-03-14

编辑:

问题不在于super(),而在于extensedbase。无论如何,typescript必须推断出Base的泛型类型,而不能指望typescript从调用super()中推断出它。

起初我会建议这样做

    class Sub<T extends {options: any}> extends Base<T> {
    constructor() {
        super({options: {foo: 123}})
    }}

但是这是行不通的,因为不允许将具体实例分配给类型参数。如果我们不这么做就会成功

    class Sub<T extends {options: any}> extends Base<T> {
    constructor(arg: T) {
        super(arg)
    }}

const inst2 = new Sub({options: {foo: 123}})
inst2.options.foo++; // ok   

我认为正确的解决办法是简单地这样做

    class Sub extends Base<{options: any}> {
    constructor() {
        super({options: {foo: 123}})
    }}

然而,仍然存在一个问题。

const inst2 = new Sub();
inst2.options.foo++; //options is any which makes sense, we said that options is any above

你知道我们为什么使用泛型吗?当我们事先不知道是什么类型的时候。因为在这种情况下,我们确切地知道类型是什么,所以我们可以安全地执行以下操作:

class Sub extends Base<{ options: {foo: number} }> {
    // or even class Sub extends Base<{ options: {foo: 123} }> {
    constructor() {
        super({options: {foo: 123}});
        this.options.foo++;
    }
}

const inst2 = new Sub();
inst2.options.foo++;

这样可以吗?当然,如果我们将选项以外的内容传递给Base,就会触发警告。因此,我们满足Base的要求,同时确保传递给super()的内容与我们所说的泛型类型一致。

 类似资料:
  • 让我们分析下面的代码片段: 以上代码不会引发任何错误。我希望它会抛出构造函数调用,在这里我传递5。 似乎构造函数的参数被推断为,其中,静态地很容易发现我将其分配给。 问题是:TypeScript在这里允许,或者换言之,被推断为,而在这种情况下,很明显它必须是一个字符串,这有什么特殊的原因吗? 我知道我可以做另一个这样的类定义: 但这里我指定了参数类型,所以这里没有推断。我也可以这样做: 也不会有任

  • 我在班里学习。出于好奇,我扩展了具有参数化构造函数的内部类。但是当我编写super(inti)来调用它时,代码不会编译。 因为内部类是外部类的一部分(成员),必须通过外部类访问它们。如何调用测试类的超级构造函数。 编译错误是:由于某些中间构造函数调用,没有外部类型的封闭实例可用

  • 为什么第一个输出有柱线 = 空?是因为在创建类 B 之前调用了 B.foo() 吗?如果是,那么为什么可以调用 B.foo()?还是因为 B.foo() 中的字段栏试图从 A 获取柱线字段但无法访问它? 我的问题与链接的问题不同,我不是在问调用顺序,我是在问为什么第一个输出为空?另一个问题不是关于字段或空变量。 我不明白B.foo中的bar变量是如何为空的,如果它是在A和B中定义的。

  • 问题内容: 我正在尝试创建一个将字段作为参数的构造函数,然后将其放入存储在超类中的字段中。这是我正在使用的代码 在超类中,我用 我有一个访问器方法 我收到一个错误“ 味道在超类中具有私有访问权 ”,但是我认为这无关紧要,因为我正在调用将其返回到字段的访问器方法? 问题答案: 您应该做什么: 在您的超类中添加一个构造函数: 在Crisps类中: 注释 对您的问题的一些评论: “在超类中,我已经用”

  • 我有一个有两个构造函数的类。 有一个具有两个构造函数的类Sample。需要在Sample类中实例化另外三个类(ClassOne,ClassTwo和ClassIII)。所有三个类都包含默认和参数化构造函数。如果调用了Sample类的默认构造函数,则应调用ClassOne,ClassTwo和ClassIII的默认辅助构造函数。如果调用Samples参数化构造函数,则调用ClassOne、ClassII

  • 问题内容: 我有两个类,和,扩展了前一个类。 具有以下构造函数: 我将注意到所有实例变量都已设置为private。 同时,具有以下构造函数: 但是,这为我的构造函数引发了“找不到符号”错误。 我尝试使用,但是我的超类的私有范围阻止了这种情况。 我发现向我的构造函数中添加字段并允许我调用超级构造函数,但是我想知道是否存在一种无需在子类构造函数中传递其所有参数的情况下调用超级构造函数的方法? 问题答案