【问题标题】:String literal argument as compile-time type name字符串文字参数作为编译时类型名称
【发布时间】:2017-08-29 07:46:10
【问题描述】:

给定以下类型:

declare namespace Word {
    interface Application { }
    interface Document { 
        Save(): void;
    }
}

我可以写多个重载如下:

interface ActiveXObject {
    new(progid: 'Word.Application'): Word.Application;
    new(progid: 'Word.Document'): Word.Document;
}

它采用各种字符串文字并返回相应的类型。因此,以下内容无法编译:

var doc = new ActiveXObject('Word.Document');

//compilation error here -- Word.Document doesn't have this method
doc.BadMethod();

是否可以编写一个返回类型为字符串字面量引用的类型的重载?

类似的东西:

interface ActiveXObject {
    new(progid: string): typefrom(progid);
}

并且编译器会将以下内容标记为无法识别的类型:

var nonexistentType = new ActiveXObject('Word.NonexistentType');

【问题讨论】:

标签: typescript


【解决方案1】:

您可以利用映射类型和查找类型。但是,您仍然需要声明一个类型来查找。

link

declare namespace Word {
    interface Application { }
    interface Document { 
        Save(): void;
    }
}
type Mapping = {
    Application: Word.Application,
    Document: Word.Document
}
interface ActiveXObject {
  new<K extends keyof Mapping>(k: K): Mapping[K]
}

var doc = new ActiveXObject('Document');

//compilation error here -- Word.Document doesn't have this method
doc.BadMethod();

如果你可以定义命名空间 Word 来导出类,你有更好的技巧。

declare namespace Word {
    export class Application { }
    export class Document { 
        Save(): void;
    }
}

interface ActiveXObject {
  new<K extends keyof typeof Word>(k: K): (typeof Word)[K]['prototype']
}

var doc = new ActiveXObject('Document');

doc.BadMethod(); // error
doc.Save(); // ok

【讨论】:

  • 我正在考虑这个,特别是因为我看到它在lib.d.ts 中用于createElement 签名。我将不得不使用接口而不是别名,因为这些映射可能分布在多个文件中,并且需要合并。 (小点——在我的特定场景中,命名空间也必须作为映射类型的键包含在内。)
  • 嗨@ZevSpitz,我想出了一个甚至需要更少重复的技巧。看看吧。
猜你喜欢
  • 1970-01-01
  • 2011-10-25
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-07
  • 1970-01-01
相关资源
最近更新 更多