繁体   English   中英

在通用函数中,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" keyof T "nope" ,并且声明的validationFuncs类型是{nope?: Methods}[]

但是如果mapping["nope"] (有效的Mapping<{nope: string}> ),那么validationFuncs在运行时将是[{nope: "nope"}] 但那不是{nope?: Methods}[] ,因为validationFuncs[0].nope"nope" 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 } 无法正常工作,因为与计算出的密钥的打字稿错误的 ,这可能固定在打字稿2.6; 不确定。

编译器应该(但没有)意识到{ [m]: m }只能保证{firstName:"firstName"}{lastname:"lastname"}{e:"e"} ,最后两个它们都是无效Method<Fields>元件(请注意在小写“n”的lastname )。 相反,类型检查器将{ [m]: m }的类型扩展为类似{ [k: string]: keyof Fields } ,这显然足够宽以匹配Method<Fields> ,而不是我理解的方式。 无论如何,它不应该进行类型检查; 这是TypeScript中的错误或设计限制。


在这两种情况下,您都没有以符合您声明的类型的方式实现代码。 我不知道你的类型是否正确,但实现是错误的,反之亦然,或其他什么。 我希望你现在有足够的信息来取得进展。 祝好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM