【发布时间】:2018-02-02 18:26:15
【问题描述】:
我以一种明显的非接口方式使用接口。
我有一个程序,它有不同类型的模块,每个模块都用一个字符串表示——为了论证,我们称它们为"text" 和"image"。
这些模块类型中的每一个都与几个数据结构相关,我们称它们为document 和transient。所以对于text 和image 中的每一个都有一个document 数据接口和一个transient 数据接口。
我使用奇怪的中间件接口在这些类型和数据结构之间建立关系:
type ModuleType = "image" | "text";
interface TextDocumentData { /* ... */}
interface ImageDocumentData { /* ... */}
interface DocumentDataMap {
"image": ImageDocumentData;
"text": TextDocumentData;
}
interface TextTransientData { /* ... */}
interface ImageTransientData { /* ... */}
interface TransientDataMap {
"image": ImageTransientData;
"text": TextTransientData;
}
然后我在这样的函数中使用它:
interface AllData<T extends ModuleType> {
doc: DocumentDataMap[T];
trn: TransientDataMap[T];
}
function getAllData<T extends ModuleType>(moduleType: T): AllData<T> { /* ... */ }
这将使getAllData("text").doc; 返回一个TextDocumentData 类型的对象。
这一切都很好(即使很难阅读)。我现在想做的是确保如果添加了新的模块类型(我们称之为table)tsc 在编译时出错,直到我添加了一个"table" 条目到DocumentDataMap 和TransientDataMap.
这是我迄今为止尝试过的:
type ModuleType = "image" | "text" | "table";
type DocumentData = TextDocumentData | ImageDocumentData | TableDocumentData;
type TransientData = TextTransientData | ImageTransientData;
type ModuleTypeMap<T> = {[m in ModuleType]: T};
interface TextDocumentData { /* ... */}
interface ImageDocumentData { /* ... */}
interface TableDocumentData { /* ... */}
interface DocumentDataMap extends ModuleTypeMap<DocumentData> {
"image": ImageDocumentData;
"text": TextDocumentData;
"table": TableDocumentData;
}
interface TextTransientData { /* ... */}
interface ImageTransientData { /* ... */}
// This should cause an error (there's no entry for tables!)
interface TransientDataMap extends ModuleTypeMap<TransientData> {
"image": ImageTransientData;
"text": TextTransientData;
}
ModuleTypeMap 类型强制使用每个可能的ModuleType 作为键,并以 T 作为值的类型。 DocumentDataMap 和 TransientDataMap 继承自此。如果我真的在真实对象上使用这些接口,这会很好,但由于它们仅用于创建字符串和数据类型之间的关系,扩展 ModuleTypeMap 不会做任何事情。
有没有办法确保接口具有某些成员?有没有更好的方法来实现字符串和数据类型/接口之间的关系?在这一点上,我觉得我远远超出了 TypeScript 中接口的预期用途......
【问题讨论】:
-
AllData会报错,所以在使用上会报错,在声明时很难报错 -
@TitianCernicova-Dragomir 您所说的用法是指运行时吗?因为 TypeScript 会将所有这些编译成
function getAllData(moduleType) { }。无论哪种方式,我都没有看到任何编译 或 运行时错误。 -
我在 ts 2.7 的
trn: TransientDataMap[T];上收到此错误Type 'T' cannot be used to index type 'TransientDataMap'
标签: typescript inheritance interface