是否可以确保对象完整性并保留属性类型?

时间:2019-02-02 08:51:37

标签: typescript

是否可以编写类型AllValidators,以确保其类型的对象具有ALL中的ValidatorName键,并且每个属性都保持其原始类型?

因此底部的const validator的类型为Validator<string>

我不想 validatoranyValidator<any>Validator<string|number|boolean>

谢谢!

type ValidatorName = 'maxLength' | 'required' | 'regexp';

type Validator<P> = {
  (value: string, param: P): boolean;
};

type AllValidators = {
  [key in ValidatorName]: ???
}

const allValidators: AllValidators = {
  maxLength: ((value: string, param: number) => false) as Validator<number>,
  required: ((value: string, param: boolean) => false) as Validator<boolean>,
  regexp: ((value: string, param: string) => false) as Validator<string>,
}

const validator = allValidators.regexp

2 个答案:

答案 0 :(得分:1)

不能有一个既受接口限制又不能根据分配的值推断其类型的变量。您可以改为使用带有类型参数的函数。类型参数可以有一个约束,但是实际的参数类型将从调用中捕获。

type ValidatorName = 'maxLength' | 'required' | 'regexp';

type Validator<P> = {
    (value: string, param: P): boolean;
};

function createAllValidators<T extends { [P in ValidatorName]: Validator<any> }>(o: T) {
    return o;
}
const allValidators = createAllValidators({
    maxLength: ((value: string, param: number) => false),
    required: ((value: string, param: boolean) => false),
    regexp: ((value: string, param: string) => false),
})

const validator = allValidators.regexp

// { maxLength: number; required: boolean; regexp: string; }
type Rules = {
    [P in keyof typeof allValidators] : (typeof allValidators[P] extends Validator<infer T>? T: never)
}

答案 1 :(得分:0)

好吧,如果您颠倒逻辑并在位置中键入并使用typeof来简单地捕获allValidators的类型,则非常简单:

type Validator<P> = {
  (value: string, param: P): boolean;
};

const allValidators = {
  maxLength: ((value: string, param: number) => false) as Validator<number>,
  required: ((value: string, param: boolean) => false) as Validator<boolean>,
  regexp: ((value: string, param: string) => false) as Validator<string>,
}

type AllValidators = typeof allValidators;

const validator = allValidators.regexp

您甚至不再需要ValidatorName(而且是否也需要AllValidators也是有争议的。)