我有一组存储源数据的SON文件.一种语言有一个文件,所有文件都具有相同的键,但值类型不同.是这样的:
// source-en.json
{
"action": ["change", "check"],
"device": ["coil", "relay"],
}
// source-pl.json
{
"action": ["wymienić", "sprawdzić"],
"device": [
{
"gender": "f",
"singular": "cewkę",
"plural": "cewki"
},
{
"gender": "m",
"singular": "przekaźnik",
"plural": "przekaźniki"
}
]
}
所以,我可以用界面来描述它们:
interface SourceEn {
action: string[],
device: string[],
}
interface SourcePl {
action: string[],
device: NounForms[],
}
interface NounForms {
gender: 'm' | 'f' | 'n' | 'pl';
singular: string;
plural: string;
}
现在,我有了消耗数据的一组类:EnConsumer
、PlConsumer
.继承自BaseConsumer
.BaseConsumer
知道如何获取源文件并将SON转换为实际数据,而具体类知道如何处理特定于语言的差异.所以,BaseConsumer
看起来是这样的:
type Source = SourceEn | SourcePl;
class BaseConsumer<T extends Source> {
public readonly action: Collection<ArrayItem<T['action']>>;
public readonly device: Collection<ArrayItem<T['device']>>;
public constructor(language: Language) {
const data = this.getData(language);
this.action = new Collection(data.action);
this.device = new Collection(data.device);
}
protected getData(language: Language): T {...}
}
class Collection<T> {
public constructor(private store: T[]) {}
}
type ArrayItem<A extends unknown[]> = A extends (infer E)[] ? E : never;
enum Language {
EN = 'en',
PL = 'pl',
}
但它不起作用.具体来说,this.device = new Collection(data.device);
行给出两个错误:
-
data.device
:
Argument of type
string[] | NounForms[]
is not assignable to parameter of typestring[]
TypeNounForms[]
is not assignable to typestring[]
TypeNounForms
is not assignable to typestring
-
this.device
:
Type
Collection<string>
is not assignable to typeCollection<Source['device']>
Typestring
is not assignable to typeSource['device']
问题源于T extends Source
代表SourceEn
和SourcePl
的联合这一事实.但对于class ConsumerPl extends BaseConsumer<SourcePl>
,ConsumerPl
类应该知道哪些接口实际应用以及哪些类型应该应用于相应的字段.
我不知道如何用TypScript表达它.我不想太明确,因为今天它支持英语和波兰语,但明天也可能是克林贡语和昆亚语.因此,冗长的条件类型不是有效的解决方案.那么如何才能使这BaseConsumer
个正确的通用呢?