我刚刚开始发现TypeScript,并且正在测试限制。我正在寻找的是一种使接口作为字段的方法,具体取决于其中一个属性的值。
例如:
type type RecursiveArray<T> = T | RecursiveArray<T>[];
type allowedTypesString = 'string' | 'email' | 'date' | 'id' | 'number' | 'boolean' | 'object';
interface IOptions {
type: RecursiveArray<allowedTypesString>,
required?: boolean,
defaultValue?: PROVIDED_TYPE,
expected?: PROVIDED_TYPE[],
transform?: (value: PROVIDED_TYPE) => any,
validate?: (value: PROVIDED_TYPE) => boolean,
regexp?: RegExp,
min?: number,
max?: number,
params?: object,
}
我希望IOptions具有:
regex
是“ string”或“ email”时,type
属性。 params
仅在type
是“对象”的情况下。min
和max
仅在type
是“数字等... 我看到我可以像在this线程中那样使用区分联合,但是正如您所看到的,type
属性是RecursiveArray<allowedTypesString>
,这意味着它可以是单个字符串,字符串数组,字符串数组,等 ...
有了工会,我可以宣布:
interface IOptionsString {
type: string,
defaultValue?: string,
expected?: string[],
regexp?: RegExp,
}
如果type
是一个字符串,将调用。但是,如果我收到一个字符串数组或一个字符串数组怎么办?
我正在做什么?否则,我将只处理单个数组,但是我想知道我在想什么在TypeScript中是可能的。
感谢您的帮助!
答案 0 :(得分:0)
如果使用实际类型对IOptions
进行参数化,然后将其转换为常见类型和依赖于该类型的特殊类型的交集,则可以使用条件类型来做您想做的事情。
要返回原始类型(例如您的示例中的PROVIDED_TYPE
),您需要将allowedTypesString
更改为从字符串类型到实际类型的映射,然后使用条件类型进行验证(即从值)。
type RecursiveArray<T> = T | RecursiveArray<T>[];
interface TypeStringMap {
'string': string;
'email': string;
'date': Date;
'id': string;
'number': number;
'boolean': boolean;
'object': object;
}
type RecursiveTypes = RecursiveArray<keyof TypeStringMap>;
type HasRegexp<T extends RecursiveTypes> =
T extends RecursiveArray<'string' | 'email'> ? { regexp: RegExp } : {}
type HasMinMax<T extends RecursiveTypes> =
T extends RecursiveArray<'number'> ? { min: number, max: number } : {}
type ReifyRecursiveType<T> =
T extends keyof TypeStringMap ? TypeStringMap[T]
: (T extends (infer U)[] ? ReifyRecursiveType<U>[] : never)
type IOptions<T extends RecursiveTypes> = {
type: T;
expected?: ReifyRecursiveType<T>[];
defaultValue?: ReifyRecursiveType<T>,
transform?: <TResult>(value: ReifyRecursiveType<T>) => TResult,
validate?: (value: ReifyRecursiveType<T>) => boolean,
} & HasRegexp<T> & HasMinMax<T>
type IStringOptions = IOptions<'string'>; // has `regexp` field
type IStringOrEmailOptions = IOptions<('string' | 'email')>; // has `regexp` field
type IEmailArrayArrayOptions = IOptions<'email'[][]>; // has `regexp` field
type INumberOptions = IOptions<'number'>; // has `min` and `max` fields