【问题标题】:Instantiate a class of type abstract class实例化一个类型为抽象类的类
【发布时间】:2021-09-04 02:19:14
【问题描述】:

函数 createBob 有一个 TS 错误,因为 Person 是一个抽象类,我无法实例化它。 我希望该函数只接受扩展 Person 且不是抽象的类。

abstract class Person {
    protected abstract type?: string
    constructor(private name: string) {}

    protected greet() {
        console.log(`Hello ${this.name}`)
    }
}


class Student extends Person {
    type = "Student" 
    constructor(type: string) {
        super(type)
    }
}

class Teacher extends Person {
    type = "teacher"
    constructor(type: string) {
        super(type)
    }
}

function createPerson(ClassThatInheritsPerson: typeof Person): Person {
    /*
    * The ClassThatInheritsPerson should only accept classes that extend Person but are not Person
    */
    return new ClassThatInheritsPerson()
}

const teacher1 = createPerson(Teacher) // should be allowed
const student1 = createPerson(Student) // should be allowed
const person = createPerson(Person) // shouldn't be allowed

【问题讨论】:

  • 由于您尝试创建不带任何参数的ClassThatInheritsPerson,因此不应同时允许StudentTeacher。这是故意的吗?

标签: typescript


【解决方案1】:

您不能像在其他语言中那样传递类型并使用它们来实例化类。您需要做的是使用new() => Person 将createPerson 的参数类型更改为构造函数。这将允许您创建 Person 的新实例,同时为抽象案例引发编译器错误:

function createPerson<T extends Person>(ctor: new() => T): T {
    return new ctor();
}

const student1 = createPerson(Student); // should be allowed
const teacher1 = createPerson(Teacher); // should be allowed
const foo =  createPerson(Foo); // typeof Foo isn't asignable to () => Person
const person1 = createPerson(Person) // Error: Cannot assign an abstract 

其他一些建议。不要让类型受保护——这对于以后区分类型很有用。您也可以将类型的类型设为字符串文字,或使用泛型参数来指定类型。这样student.type 之类的就不会输入 string,而是输入 'student'。

abstract class Person<T extends string> {
    constructor(public readonly type: T) { }
}

class Student extends Person<'Student'> {
    constructor() {
        super('Student');
    }
}

class Teacher extends Person<'teacher'> {
    constructor() {
        super('teacher');
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2014-09-08
    相关资源
    最近更新 更多