鉴于这些Typescript类型:
// Validation types
type Methods = 'firstName' | 'lastName' | 'email'
type Method<T> = {[K in keyof T]?: Methods }
type Row<T> = keyof T | Method<T>
type Mapping<T> = Array<Row<T>>
// Fields that will be accepted
type Fields = {
firstName: string
lastname: string
e?: string
}
这个数据:
// Data object, holding the form submission
const data: Fields = {
firstName: 'John',
lastname: 'Doe',
e: 'john@example.com'
}
// Map validation methods to the data fields
const mapping: Mapping<Fields> = [
'firstName',
'lastname',
{
e: 'email'
}
]
为什么这样做:
const validationFuncs: Method<Fields>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
// validationFuncs[0].firstName // works
但这不是吗?
function validate<T>(mapping: Mapping<T>) {
const validationFuncs: Method<T>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
}
答案 0 :(得分:2)
Method<T>
的值必须为Methods
,且只能是"firstName"
,"lastName"
或"email"
。在您的通用示例中:
function validate<T>(mapping: Mapping<T>) {
const validationFuncs: Method<T>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
}
类型T
可以是任何内容......例如{nope: string}
。在这种情况下,keyof T
为"nope"
,声明的validationFuncs
类型为{nope?: Methods}[]
。
但如果mapping
为["nope"]
(有效Mapping<{nope: string}>
),则validationFuncs
在运行时将为[{nope: "nope"}]
。但这不是{nope?: Methods}[]
,因为validationFuncs[0].nope
是"nope"
而不是undefined
或Methods
的三个允许值中的任何一个。所以编译器会警告你。这一切都对我有意义。
在非通用的“工作”示例中:
const validationFuncs: Method<Fields>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
发生了一些奇怪的事情。 Method<Fields>
相当于
type MethodFields = {
firstName?: Methods
lastname?: Methods
e?: Methods
}
但是{ [m]: m }
isn't working properly because of a TypeScript bug with computed keys的类型检查,其中可能在TypeScript 2.6中为fixed;不确定。
编译器应该(但没有)意识到{ [m]: m }
只能保证{firstName:"firstName"}
,{lastname:"lastname"}
或{e:"e"}
,其中最后两个是不有效Method<Fields>
元素(注意lastname
中的小写“n”)。相反,类型检查器会将{ [m]: m }
的类型扩展为类似{ [k: string]: keyof Fields }
的类型,这显然足够宽以匹配Method<Fields>
,而不是我理解的方式。无论如何,它不应该进行类型检查;这是TypeScript中的错误或设计限制。
在这两种情况下,您都没有以符合您声明的类型的方式实现代码。我不知道你的类型是否正确,但实现是错误的,反之亦然,或其他什么。我希望你现在有足够的信息来取得进展。祝你好运!