我具有以下自定义类型和接口:
export type MultiMedia = 'image' | 'audio' | 'video';
export type FieldType = 'string' | 'number' | 'boolean' | MultiMedia;
export interface Field {
name: string,
label: string,
type: FieldType,
validator: <T>(val: T) => boolean,
bounds: { lower: number; upper: number }
}
export interface Theme {
title: string,
logoPath: string,
tags: string[],
fields: Field[]
}
由于字段类型彼此不同,因此我在validator
接口中将Field
定义为通用方法。当我想制作实现Field
接口打字稿的对象文字时
类型'(val:string)=>布尔值'不能分配给类型'(val:T)=>布尔值。
const fields: Field[] = [
{
name: "firstName",
label: "First Name",
type: "string",
bounds: { lower: 1, upper: 1 },
validator: (val: string) => {
return val.length > 20;
}
}
我可以按以下方式更改Field
界面来解决该问题。
export interface Field<T> {
name: string,
label: string,
type: FieldType,
validator: (val: T) => boolean,
bounds: { lower: number; upper: number }
}
但是打字稿抱怨fields
界面中的Theme
属性。
通用类型“字段”需要1个类型参数。
答案 0 :(得分:1)
我认为这里的问题是Field
基本上是union,因为您希望它是或者是string
字段,或 number
字段等。我这样做的方法是创建一个通用的SpecificField<F>
接口,该接口表示从每个字段类型F
到其验证器的约束,以及然后将Field
用作所有SpecificField<F>
类型的并集的类型别名:
首先让我们定义字段映射,以便我们知道验证器应接受的内容
interface FieldMapping {
image: HTMLImageElement; // guessing
audio: HTMLAudioElement; // guessing
video: HTMLVideoElement; // guessing
string: string;
number: number;
boolean: boolean;
}
现在是SpecificField<F>
界面:
export interface SpecificField<F extends FieldType> {
name: string;
label: string;
type: F;
validator: (val: FieldMapping[F]) => boolean;
bounds: { lower: number; upper: number };
}
您可以看到SpecificField<string>
的{{1}}中的type
和仅接受"string"
值的validator
。然后我们将string
变成一个并集,这可能是这样的:
Field
这使用mapped type获取每个字段作为属性,然后通过looking up获取所有属性的并集。您可以验证其计算结果为:
type Field = { [F in FieldType]: SpecificField<F> }[FieldType];
然后,您可以验证以下各项是否有效:
type Field = SpecificField<"string"> | SpecificField<"number"> |
SpecificField<"boolean"> | SpecificField<"image"> | SpecificField<"audio"> |
SpecificField<"video">
好的,希望能有所帮助;祝你好运!
答案 1 :(得分:0)
您的最后一个示例将起作用,除了在使用T
接口时(在Field
接口声明和常量{{1中)都需要声明Theme
的类型。 }}声明),而不是在声明fields
时:
validator
编辑:
此外,如果要将export type MultiMedia = 'image' | 'audio' | 'video';
export type FieldType = 'string' | 'number' | 'boolean' | MultiMedia;
export interface Field<T> {
name: string,
label: string,
type: FieldType,
validator: (val: T) => boolean,
bounds: { lower: number; upper: number }
}
export interface Theme {
title: string,
logoPath: string,
tags: string[],
fields: Field<string>[]
}
const fields: Field<string>[] = [
{
name: "firstName",
label: "First Name",
type: "string",
bounds: { lower: 1, upper: 1 },
validator: (val: string) => {
return val.length > 20;
}
}
]
的类型限制为T
之一,则可以执行以下操作:
FieldType