字符串文字参数作为编译时类型名称
问题描述:
考虑以下几种类型:字符串文字参数作为编译时类型名称
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');
答
您可以利用类型映射和查找类型。不过,你仍然需要声明一种查找类型。
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,我想出了一个甚至需要更少重复的技巧。一探究竟。 –
有趣的问题。相关/可能的重复:[动态加载打字稿类 - 反射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
@ Pac0 Both问题涉及在运行时从字符串创建实例;我对编译时感兴趣。 AFAICT,所有的答案要么将结果转换为明确的类型,要么只是使用'any'。 –
是的,我没有标记你的帖子,并正在阅读这些。恐怕没有优雅简单的答案,只要你愿意。但我不是专家,所以我不会将我的意见转化为答案。 – Pac0