【问题标题】:Is the Function interface missing a new() signature?Function 接口是否缺少 new() 签名?
【发布时间】:2014-11-21 06:35:25
【问题描述】:

我有一些看起来像这样的通用代码:

interface IClass<T> {
    new (...args: any[]): T;
}

function someFactory<T>(a: IClass<T>): T {
    return new a();
}

class Foo { }

var f = someFactory(Foo);

并且f 被正确推断为Foo。该函数还禁止非新类型。

此外,编译器允许以下情况,f 的类型为any

function Foo() { }

var f = new Foo();

所以我希望以下通用代码可以工作:

interface IInstance<T> {
    constructor: IClass<T>;
}

function extractType<T>(a: IInstance<T>): IClass<T> {
    return a.constructor;
}

class Foo { }

var f = new Foo();
var t = extractType(f);

但我在提取类型的 f 参数上收到此错误:

“Foo”类型的参数不能分配给“IInstance”类型的参数。

如果我放松打字:

function extractType<T extends Object>(a: T): IClass<T> {
    return a.constructor;
}

class Foo { }

var f = new Foo();
var t = extractType(f);

我在a.constructor 收到此错误:

类型“Function”不可分配给类型“IClass”。

由于一个函数是新的,我希望这些模式可以工作。如果我使用 new() 签名扩展 Function 接口,它们都可以工作:

interface Function {
    new (...args: any[]): any;
}

那么,Function 是否缺少new() 签名,还是有其他方式来表达我的意图?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这里的根本原因是 TypeScript 实际上并没有将 constructor 属性添加到作为类实例的对象。

    您在extractType 中使用的constructor 属性实际上存在只是因为属性访问使用操作数的表观类型,它将全局接口Object 的成员添加到该类型中。

    从技术上讲,这段代码有效,但显然不能推广到所有类:

    class Foo {
        'constructor': typeof Foo;
    }
    
    var f = new Foo();
    var t = extractType(f); // t: IClass<Foo>
    

    基本上extractType 不能在 TypeScript 中以一般方式编写,因为构造函数和对象类型之间没有精确的 1:1 对应关系。你可能有这样的事情:

    interface MyObjectType { /* ... */ }
    var foo1: {
        new(): MyObjectType;
        xx: number;
    };
    var foo2: {
        new(): MyObjectType;
        yy: string;
    };
    var x = Math.random() > 0.5 ? new foo1() : new foo2(); // x: MyObjectType
    var t = extraType(x); // t: typeof foo1, or t: typeof foo2?
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多