TypeScript 索引类型对象和记录之间的断开推理

uwopmtnx  于 8个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(248)

TypeScript版本: 2.2.2
代码

  1. interface Errors {
  2. [field: string]: {
  3. key: string
  4. message: string
  5. }
  6. }
  7. const errors: Errors = {}
  8. function genericObjectFunction<K extends string, V>(obj: Record<K, V>): [K, V][] {
  9. return []
  10. }
  11. /*
  12. Argument of type 'Errors' is not assignable to parameter of type 'Record<string, never>'.
  13. Index signatures are incompatible.
  14. Type '{ key: string; message: string; }' is not assignable to type 'never'.
  15. */
  16. genericObjectFunction(errors)

尽管类型看起来大致兼容,但这是合法的:

  1. const errorRecord: Record<string, { key: string, message: string }> = errors

预期行为:

genericObjectFunction(errors) 应该能够编译。

4ngedf3f

4ngedf3f1#

这个失败的原因是

  1. interface Errors {
  2. [field: string]: {
  3. key: string
  4. message: string
  5. };
  6. }

没有离散的键,所以记录是空的。 Record<K, V> 类型是通过将键Map到值来定义的,由于没有已知的值,通用示例化没有成员。
考虑

  1. const errors = { // no explicit type, inferred type has members, still compatible with interface.
  2. password: {
  3. key: 'minimumComplexity',
  4. message: 'Password must contain at least one non alphanumeric character'
  5. }
  6. };
  7. function genericObjectFunction<K extends string, V>(obj: Record<K, V>): [K, V][] {
  8. return [];
  9. };
  10. const genericErrors = genericObjectFunction(errors);

编辑:

这里有一个带有解决方法的例子(注意:重载顺序很重要)

  1. interface Errors {
  2. [field: string]: {
  3. key: string
  4. message: string
  5. }
  6. }
  7. const errors: Errors = {
  8. password: {
  9. key: 'minimumComplexity',
  10. message: 'Password must contain at least one non alphanumeric character'
  11. }
  12. };
  13. function genericObjectFunction<K extends string, V>(obj: Record<K, V>): [K, V][];
  14. function genericObjectFunction<V>(obj: { [field: string]: V }): [string,{[P in keyof V]:V[P]}][];
  15. function genericObjectFunction<K extends string, V>(obj: Record<string, V>): [K, V][]{
  16. return [];
  17. };
  18. const typeInferredErrors = {
  19. password: {
  20. key: 'minimumComplexity',
  21. message: 'Password must contain at least one non alphanumeric character'
  22. }
  23. };
  24. const genericErrorsX = genericObjectFunction(errors);
  25. const genericErrorsY = genericObjectFunction(typeInferredErrors);
展开查看全部
pcww981p

pcww981p2#

是的,我尝试了重载作为POC,它可以工作。只是在几十个函数上这样做有点烦人:)
我理解Record试图从显式键和值中提取信息,但两者之间是否存在简单的翻译?

laik7k3q

laik7k3q3#

我理解Record试图从显式键和值中提取信息,但两者之间是否存在简单的翻译?
可能有,但我觉得将两者混合可能会导致错误。
这也有可能是一个bug。我不相信是,但我肯定有可能犯错。

krcsximq

krcsximq4#

从v3.3.3版本开始,不再产生错误。
Playground链接:v3.1.6,有错误
Playground链接:v3.3.3,无错误
这是否应该关闭?

相关问题