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

时间:2018-10-02 23:19:53

标签: 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]
}));

1 个答案:

答案 0 :(得分:3)

It's explained here

  

字符串文字类型的工作方式是字符串文字表达式   必须由字符串文字类型(或并集)在上下文中键入   包含字符串文字类型)以将check输入为字符串   文字类型而不是字符串。

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

另一种解决方法是为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'
    }]
}));