字符串文字参数作为编译时类型名称

问题描述:

考虑以下几种类型:字符串文字参数作为编译时类型名称

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

其采取各种字符串文本,并返回相应类型:

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

如下我可以写多个重载。因此,下面可能不会编译:

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'); 
+0

有趣的问题。相关/可能的重复:[动态加载打字稿类 - 反射Typescript](https://stackoverflow.com/questions/15338610/dynamically-loading-a-typescript-class-reflection-for-typescript)和 [如何将字符串值转换为在Angular 2中键入](https://stackoverflow.com/questions/35356988/how-to-convert-a-string-value-to-type-in​​-angular-2) – Pac0

+0

@ Pac0 Both问题涉及在运行时从字符串创建实例;我对编译时感兴趣。 AFAICT,所有的答案要么将结果转换为明确的类型,要么只是使用'any'。 –

+0

是的,我没有标记你的帖子,并正在阅读这些。恐怕没有优雅简单的答案,只要你愿意。但我不是专家,所以我不会将我的意见转化为答案。 – Pac0

您可以利用类型映射和查找类型。不过,你仍然需要声明一种查找类型。

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 
+0

我正在考虑这个问题,特别是因为我看到它在'lib.d.ts'中用于'createElement'签名。我将不得不使用接口而不使用别名,因为这些映射可能分布在多个文件中,而且需要合并。 (小点 - 在我的具体情况下,名称空间也必须包含为映射类型的键。) –

+2

嗨@ZevSpitz,我想出了一个甚至需要更少重复的技巧。一探究竟。 –