Typescript - 类型映射在泛型函数中失败
Typescript - type mapping fails inside a generic function
给定这些 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;
})
}
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
的三个允许值中的任何一个。所以编译器会警告你。这一切对我来说都很有意义。
在您的非通用 "working" 示例中:
const validationFuncs: Method<Fields>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
发生了一些奇怪的事情。 Method<Fields>
等同于
type MethodFields = {
firstName?: Methods
lastname?: Methods
e?: Methods
}
但是TypeScript 2.6中{ [m]: m }
isn't working properly because of a TypeScript bug with computed keys which might be fixed的类型检查;不确定。
编译器应该(但没有)意识到 { [m]: m }
只能保证是 {firstName:"firstName"}
、{lastname:"lastname"}
或 {e:"e"}
,其中最后两个是不是有效的Method<Fields>
元素(注意lastname
中的小写"n")。相反,类型检查器将 { [m]: m }
的类型扩展为类似 { [k: string]: keyof Fields }
的类型,这显然足够宽以匹配 Method<Fields>
,但我不明白如何。无论如何,它会在不应该检查的时候进行检查;这是 TypeScript 中的错误或设计限制。
在这两种情况下,您都没有以符合您声明的类型的方式实现您的代码。我不知道你的类型是否正确但实现是错误的,反之亦然,或者其他什么。我希望你现在有足够的信息来取得进展。祝你好运!
给定这些 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;
})
}
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
的三个允许值中的任何一个。所以编译器会警告你。这一切对我来说都很有意义。
在您的非通用 "working" 示例中:
const validationFuncs: Method<Fields>[] = mapping.map(m => {
return typeof m === 'string' ? { [m]: m } : m;
})
发生了一些奇怪的事情。 Method<Fields>
等同于
type MethodFields = {
firstName?: Methods
lastname?: Methods
e?: Methods
}
但是TypeScript 2.6中{ [m]: m }
isn't working properly because of a TypeScript bug with computed keys which might be fixed的类型检查;不确定。
编译器应该(但没有)意识到 { [m]: m }
只能保证是 {firstName:"firstName"}
、{lastname:"lastname"}
或 {e:"e"}
,其中最后两个是不是有效的Method<Fields>
元素(注意lastname
中的小写"n")。相反,类型检查器将 { [m]: m }
的类型扩展为类似 { [k: string]: keyof Fields }
的类型,这显然足够宽以匹配 Method<Fields>
,但我不明白如何。无论如何,它会在不应该检查的时候进行检查;这是 TypeScript 中的错误或设计限制。
在这两种情况下,您都没有以符合您声明的类型的方式实现您的代码。我不知道你的类型是否正确但实现是错误的,反之亦然,或者其他什么。我希望你现在有足够的信息来取得进展。祝你好运!