TypeScript const 断言

当对字面量使用 const 断言/const assertions 时,

  • 字面量中类型不会再宽泛,比如 hello 不再会认为是 string 类型,就是 hello 类型
  • 对象属性变成 readonly
  • 数组变成 readonly 的元组(tuple) 类型

示例:

// Type '"hello"'
let x = "hello" as const;

// Type 'readonly [10, 20]'
let y = [10, 20] as const;

// Type '{ readonly text: "hello" }'
let z = { text: "hello" } as const;

相对 const 声明的字面量具体有什么区别,考察如下代码:

function getShapes() {
  const result = [
    { kind: "circle", radius: 100 },
    { kind: "square", sideLength: 50 },
  ];
  return result;
}

此时如果我们观察上述函数的返回类型可得到:

({
  kind: string;
  radius: number;
  sideLength?: undefined;
} | {
  kind: string;
  sideLength: number;
  radius?: undefined;
})[]

即,函数返回的为一个 union 类型的数组,元素中都出现的 kind 字段没影响,而另外两个字段因为只分别在一个对象中出现过,所以会形成一个 undefined 类型。

这样严格模式 strict:true 下使用的时候就会报错:

let num=0;

for (const shape of getShapes()) {
  if (shape.kind === "circle") {
// ❌Type 'number | undefined' is not assignable to type 'number'.
    num = shape.radius
  } else {
// ❌Type 'number | undefined' is not assignable to type 'number'.
    num = shape.sideLength
  }
}

image

如果改成 const 断言,返回的则是字面量原有未经过转换过的类型:

function getShapes() {
  const result = [
    { kind: "circle", radius: 100 },
    { kind: "square", sideLength: 50 },
- ];
+ ] as const;
  return result;
}

观察此时返回的类型为:

 readonly [{
    readonly kind: "circle";
    readonly radius: 100;
}, {
    readonly kind: "square";
    readonly sideLength: 50;
}]

此时通过 shape.kind 进行类型区分后,原先两个对象就被成功分离开了,使用时自动提示也只会提供对应对象上有的字段:

for (const shape of getShapes()) {
  if (shape.kind === "circle") {
// ✅
    num = shape.radius
  } else {
// ✅
    num = shape.sideLength
  }
}
for const

相关资源