typescript - 在映射操作期间创建时,字符串文字联合类型无法编译

标签 typescript

当我们使用 map 时,字符串文字联合类型会失败,但当我们直接创建数组时不会。

这是一个Fiddle from the Playground .

type Unit = 'g' | 'ml';

class Measurement { 
    unit: Unit;
}

class Thing { 
    measurements: Measurement[];
}

// works
const things: Thing[] = [{
    measurements: [{
        unit: 'g'
    }]
}];

// fails
const thingsToo: Thing[] = Array.from({ length: 5 }).map((i) => ({
    measurements: [{
        unit: 'g'
    }]
}));

错误:

Type '{ measurements: { unit: string; }[]; }[]' is not assignable to type 'Thing[]'.
  Type '{ measurements: { unit: string; }[]; }' is not assignable to type 'Thing'.
    Types of property 'measurements' are incompatible.
      Type '{ unit: string; }[]' is not assignable to type 'Measurement[]'.
        Type '{ unit: string; }' is not assignable to type 'Measurement'.
          Types of property 'unit' are incompatible.
            Type 'string' is not assignable to type 'Unit'.

为什么在 map 期间会发生这种情况?我们该如何预防?

一种方法是转换为Measurement。目前还不清楚为什么这是必要的,而且它也比不转换更冗长,所以我们宁愿不使用转换,除非那是唯一的方法。

// works
const thingsToo: Thing[] = Array.from({ length: 5 }).map((i) => ({
    measurements: [{
        unit: 'g'
    } as Measurement]
}));

最佳答案

It's explained here

The way string literal types work is that a string literal expression must be contextually typed by a string literal type (or a union containing a string literal type) in order to type check as a string literal type instead of as string.

在您的代码中,'g' 字符串文字类型被扩展为 string,因为没有上下文可以将其保留为 Array 中的文字...映射表达式。

另一种解决方法是为 map 回调添加显式返回类型:

type Unit = 'g' | 'ml';

class Measurement { 
    unit: Unit;
}

class Thing { 
    measurements: Measurement[];
}

// works
const things: Thing[] = [{
    measurements: [{
        unit: 'g'
    }]
}];

// works
const thingsToo: Thing[] = Array.from({ length: 5 }).map((i): Thing => ({
    measurements: [{
        unit: 'g'
    }]
}));

关于typescript - 在映射操作期间创建时,字符串文字联合类型无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52617679/

相关文章:

css - 从 Typescript Angular 获取 CSS 参数

typescript - 如何迭代 typescript 字符串文字?

javascript - 无法呈现在运行时动态设置的集合

javascript - 如何在 typescript 和 angular 中使用 $scope.$on?

rest - angular 2触发excel下载

typescript - 为什么兼容的重载签名需要 `Subject & Array<Value>`?

javascript - 在 Jquery 每个循环中使用 TypeScript 变量

ios - 角标(Badge)数量始终为1(云函数)

html - Angular 6输入类型数字并显示逗号后2位数字

typescript - cucumber 场景大纲 : Passing space strings "" as value in Examples table