我有一些看起来像这样的接口:
export enum SortValueType {
String = 'string',
Number = 'number',
Date = 'date',
}
export interface SortConfig {
key: string;
direction: SortDirection;
type: SortValueType;
options?: {
sortBy?: 'year' | 'day';
};
}
我想扩展它,以便options.sortBy
的可能类型应取决于type
。我正在根据type
创建迭代对象,因此不可能创建type
为string
并且options.sortBy
的值为year
的对象。 / p>
这是getIteratee
函数:
private getIteratee(config: SortConfig) {
if (config.type === SortValueType.String) {
return item => _lowerCase(item[config.key]);
}
if (config.type === SortValueType.Date) {
const sortBy = _get(config, 'options.sortBy') as 'year' | 'day';
if (!!sortBy && sortBy === 'year') {
return item =>
!!item[config.key]
? new Date(item[config.key]).getFullYear()
: undefined;
}
if (!!sortBy && sortBy === 'day') {
return item =>
!!item[config.key]
? new Date(item[config.key].toJSON().split('T')[0])
: undefined;
}
}
return config.key;
}
我也愿意接受更通用的解决方案
答案 0 :(得分:2)
我认为您想要这样的东西:
export enum SortValueType {
String = 'string',
Number = 'number',
Date = 'date',
}
type SortDirection = string;
export interface SortConfig<T extends SortValueType> {
key: string;
direction: SortDirection;
type: T;
options:
T extends SortValueType.Date
? { sortBy: 'year' | 'day'; }
: { sortBy?: undefined };
}
// OK:
let dateConfig: SortConfig<SortValueType.Date> = {
key: "key",
direction: "left",
type: SortValueType.Date,
options: { sortBy: 'year' }
}
// Not OK:
let numberConfig: SortConfig<SortValueType.Number> = {
key: "key",
direction: "left",
type: SortValueType.Number,
options: { sortBy: 'year' }
}
sortBy?: undefined
是必需的,因为TypeScript在默认情况下不会阻止额外的属性。如果您仅使用{}
,则{ sortBy: 'year' }
实际上是有效的,因为它可以分配给{}
。
您可以从此处调整options
的确切类型,具体取决于您希望每种类型的选项起作用的程度。
要使getIteratee正常工作,您需要将参数更改为SortConfig<any>
,定义一个类型保护,并使用它来缩小每种情况的类型。像这样:
function isConfigType<T extends SortValueType>(
config: SortConfig<any>, type: T
): config is SortConfig<T> {
return config.type === type;
}
function getIteratee(config: SortConfig<any>) {
if (isConfigType(config, SortValueType.String)) {
// The type of 'config' here is SortConfig<SortValueType.String>;
} ...
}