[英]Typescript Interface - make type of one property dependent of type of another property
I have some Interfaces which look like this:我有一些看起来像这样的接口:
export enum SortValueType {
String = 'string',
Number = 'number',
Date = 'date',
}
export interface SortConfig {
key: string;
direction: SortDirection;
type: SortValueType;
options?: {
sortBy?: 'year' | 'day';
};
}
I would like to make it possible to extend this so that the possible types of options.sortBy
should be dependent on the type
.我想让扩展它成为可能,以便
options.sortBy
的可能类型应该取决于type
。 I am creating iteratees depending on type
so it should not be possible to create an Object where type
is string
and options.sortBy
has a value of year
.我正在根据
type
创建迭代器,因此应该无法创建type
为string
且options.sortBy
值为year
的 Object 。
This is the getIteratee
function:这是
getIteratee
function:
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;
}
I am also open to more generic solutions我也对更通用的解决方案持开放态度
I think you want something like this:我想你想要这样的东西:
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' }
}
The sortBy?: undefined
is required, because TypeScript doesn't block extra properties by default. sortBy?: undefined
是必需的,因为默认情况下 TypeScript 不会阻止额外的属性。 If you just use {}
then { sortBy: 'year' }
is actually valid, as it is assignable to {}
.如果您只使用
{}
,那么{ sortBy: 'year' }
实际上是有效的,因为它可以分配给{}
。
You can tweak the exact type of options
from there, depending on how exactly you want each type's options to work.您可以从那里调整
options
的确切类型,具体取决于您希望每种类型的选项如何工作。
To make getIteratee work nicely, you'll want to change the parameter to SortConfig<any>
, define a type guard, and use that to narrow down the type for each case.为了使 getIteratee 正常工作,您需要将参数更改为
SortConfig<any>
,定义类型保护,并使用它来缩小每种情况的类型。 Like so:像这样:
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>;
} ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.