类型不能分配给泛型类型

时间:2017-04-08 20:26:26

标签: typescript

为什么不编译?

interface ITest { ... }    

class Test implements ITest { ... }

class Factory<T extends ITest> {
    constructor(private _Test: typeof Test) { }

    create(): T {
        return new this._Test();
    }
}

它提供了Type 'Test' is not assignable to type 'T'. (property) Factory<T extends ITest>._Test: new () => Test

我如何才能让它发挥作用

create(): ITest

或通过

private _Test: any

两者都不会真正沟通(代码方式)我所追求的。我能用它做任何事情吗?

1 个答案:

答案 0 :(得分:6)

  

为什么不进行编译?

它没有编译,因为_Test的类型是typeof Test。这可能令人困惑,所以让我试着打破它:

打字稿添加&#34;类型&#34;通过javascript的世界为您提供了一种说法&#34;我希望这个对象能够为他们提供所有这些属性和操作。&#34;。从本质上讲,这只是type system所做的。

Typescript具有typeof运算符,其作用类似type query作为获取&#34;类型&#34;的方式。在类型注释(:)的右侧使用来自实例化对象typeof为您提供了一种方式来说明&#34;无论该对象具有什么属性和操作,我都想捕获它们并重用它们来检查另一个对象的类型&#34;。

以下是使用此typeof运算符的示例。

let myObject = {
    a: 'a string',
    b: 5,
    c: false
};

// notice that the `typeof` operator is on the right of the `:`
function takesATypeOfMyObject(obj: typeof myObject) {
    // highlight over `a`, `b`, or `c` to see their type
    obj.a // (property) a: string
    obj.b // (property) b: number
    obj.c // (property) c: boolean
}

myObject是一个普通的javascript对象文字。函数takesATypeOfMyObject是一个函数,其中一个参数obj的类型注释为typeof myObject。该函数表示可以接受与对象myObject具有相同属性的任何对象。

这不应与只返回字符串的javascript&n; typeof运算符混淆。打字稿typeof运算符是其类型系统的一部分。请记住,当typescript编译为javascript时,类型和类型注释就会消失。

要理解的另一个重要事项是打字稿中的类如何工作。课程是一种双刃剑。在打字稿中,类充当两者:

  • 类型 - 与您可以对对象执行的属性和操作的定义一样。和
  • 一样
  • 一个构造函数 - 就像在具体function中,您可以使用new调用以获取所提及的类型

使用类型注释typeof MyClass可能很诱人,但这很可能不是您想要的。

考虑以下示例:

// define a class Animal
// this creates the type definition of `Animal` as well as
// the constructor to create an `Animal`
class Animal {
    makeNosie() { return 'grrr'; }
}

// use the constructor to create an object of type `Animal`
let myAnimal = new Animal();
// now `myAnimal` has an inferred type of `Animal`

// declare an object to of type `Animal` but instead of using
// the `Animal` constructor, just define an object literal that
// conforms to the type of Animal
let dog: Animal = {
    makeNosie: () => 'woof'
};
// the type of dog has been declared explicitly and typescript
// just checks to see if it conforms to the type

所以希望你看到,如果你想让一个对象符合一个类创建的类型,你就不要使用typeof运算符,你只需说&#34; Animal&#34;,不是typeof Animal

但是这给我们带来了一个问题:如果你这样做会怎么样?

请记住,typeof运算符会尝试捕获要重用的类型。由于class es定义了一个类型和new能够创建该类型对象的函数, typeof Animal实际正在做的是查询Animal的构造函数的类型< /强>

好的,现在我们终于可以深入挖掘您的代码,了解它为什么不编译。以下是您粘贴的原始代码:

interface ITest { }    

class Test implements ITest { }

class Factory<T extends ITest> {
    constructor(private _Test: typeof Test) { }

    create(): T {
        return new this._Test();
    }
}

查看constructor的{​​{1}}。你在这段代码中说的是&#34;我的班级Factory的{​​{1}}接受任何符合Test的构造函数的Object。这是一个非常复杂的类型(可能不是你想要的)。

请尝试使用此代码:

constructor

Factory的类型描述已更改为interface ITest { } class Test implements ITest { } class Factory<T extends ITest> { constructor(private _Test: new() => T) { } create(): T { return new this._Test(); } } ,这表示&#34; Factory的构造函数接受任何返回类型{{_Test的函数new() => T 1}}&#34;

希望这是你想要的。

我希望我能帮助您解决问题,并向您展示打字稿的强大功能。打字稿试图做一个非常雄心勃勃和疯狂的事情:为任何可能的JavaScript添加完整类型。我认为他们做得很好。