TypeScript const断言和声明之间有什么区别?

时间:2019-03-18 21:59:28

标签: typescript typescript3.0

我刚刚了解到TypeScript 3.4 RC中新的const断言功能,但看不到它与使用const声明有什么不同。

我使用announcement page中的示例对此进行了测试,该示例显然演示了如何使用as constconst断言)防止文字类型扩展(例如,"circle"扩展为string

// Example from official announcement
function getShapes() {
  let result = [
    { kind: "circle", radius: 100 },
    { kind: "square", sideLength: 50 },
  ] as const;

  return result;
}

for (const shape of getShapes()) {
  if (shape.kind === "circle") {
    console.log("Circle radius", shape.radius);
  } else {
    console.log("Square side length", shape.sideLength);
  }
}

// Output:
// Circle radius 100
// Square side length 50

但是,当我删除const断言并改用const声明时,编译器输出控制台输出中没有任何变化,也没有引发错误。 >

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

  return result;
}

那有什么区别?公告页面列出了使用const断言的三个原因:

  

•该表达式中的文字类型都不应扩展(例如,不要从“ hello”到字符串)
  •对象文字获取只读属性
  •数组文字变成只读元组

但是它没有解释断言和声明之间的区别。

2 个答案:

答案 0 :(得分:2)

此示例使用console.log测试推断的类型。 console.log不太关心其参数类型,因此在两种情况下都没有错误。

如果测试需要更具体的类型,则结果会不同:

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

  return result;
}

for (const shape of getShapes()) {
  if (shape.kind === "circle") {
    const radius: number = shape.radius;
  } else {
    const length: number = shape.sideLength;
  }
}

启用--strictNullChecks时,会出现两个错误:

t.ts:25:11 - error TS2322: Type 'number | undefined' is not assignable to type 'number'.
  Type 'undefined' is not assignable to type 'number'.

25     const radius: number = shape.radius;
             ~~~~~~

t.ts:29:11 - error TS2322: Type 'number | undefined' is not assignable to type 'number'.
  Type 'undefined' is not assignable to type 'number'.

29     const length: number = shape.sideLength;
             ~~~~~~

正如为此功能所宣传的,使用as const断言使编译器推断出精确类型时没有错误。

作为参考,以下是根据getShapes()声明从const返回类型推断出的类型:

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

如您所见,kind扩展为string,并且数组元素类型是具有声明了所有属性的元素的联合,只有其中一些在某些联合成员中是可选的-这就是为什么例如,shape.radius不会在控制台日志中显示任何错误-console.log会很高兴地记录undefined,如果工会成员的类型错误。

以下是根据断言getShapes()断定的as const返回类型的类型:

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

现在它是只读的元组类型,而不是数组,并且它对每个元组成员都有精确的类型(并且kind是正确的文字类型,如预期的那样)。

答案 1 :(得分:1)

const声明是一个变量声明,声明后不能更改。这是Typescript支持的Javascript功能。

const x ={ n: 10} ;
x.n = 11; //ok
x= { n:11}; // error 

const断言是一种类型断言,会对您描述的断言目标产生影响。

const x ={ n: 10} as const;
x. n = 11; // error n is readonly