TypeScript const 和 const 与 as const

Posted

技术标签:

【中文标题】TypeScript const 和 const 与 as const【英文标题】:TypeScript const and const with as const 【发布时间】:2021-07-24 04:31:15 【问题描述】:

据我所知,TypeScript 将 const string 变量视为不可变类型变量,只有该值而没有其他可能的值。我一直认为在其中添加as const 是多余的。

为什么我在示例的第二部分得到以下内容?

“字符串”类型的参数不能分配给类型参数...

例子:

declare function each<T extends [any] | any[]>(cases: ReadonlyArray<T>): (name: string, fn: (...args: T) => any, timeout?: number) => void;

const foo1 = 'FOO' as const;
const bar1 = 'BAR' as const;

declare function action1(value: typeof foo1 | typeof bar1): void;

each([
  [foo1],
])('test name', (value) => 
  // okay
  action1(value);
);

const foo2 = 'FOO';
const bar2 = 'BAR';

declare function action2(value: typeof foo2 | typeof bar2): void;

each([
  [foo2],
])('test name', (value) => 
  // Argument of type 'string' is not assignable to parameter of type '"FOO" | "BAR"'.(2345)
  action2(value);
);

Playground sample above is here.

【问题讨论】:

【参考方案1】:

即使您的问题的第一部分(使用 as const)没有警告任何错误,它仍然不起作用,因为 each 方法未编译为 javascript 代码,因此执行失败。

尽管您的示例试图解决 const 在缩小期间的行为问题,但我认为它太复杂了。您可能会发现以下关于 typescript 项目的建议问题很有用

Support Const Type Constraint

【讨论】:

【参考方案2】:

TS 能够推断所有类型。你应该给一点爱))) 只需添加额外的泛型来帮助 TS 找出所有类型。 TS 足够聪明,即使没有as const,也可以确定const foo='FOO' 是不变的。

declare function each<U extends string, V extends U[], T extends V>(cases: ReadonlyArray<T>): (name: string, fn: (...args: T) => any, timeout?: number) => void;


const foo1 = 'FOO' as const;
const bar1 = 'BAR' as const;

declare function action1(value: typeof foo1 | typeof bar1): void;

each([
  [foo1],
])('test name', (value) => 
  action1(value);
);

const foo2 = 'FOO';
const bar2 = 'BAR';

declare function action2(value: typeof foo2 | typeof bar2): void;

each([
  [foo2],
])('test name', value => action2(value)); // ok

如您所见,我添加了额外的 U 和 V 泛型。

请记住,如果您无法推断出某种类型,请尝试添加更多泛型))这条规则在 80% 的时间里都有效)

Playground

为什么在示例的第二部分中出现“'string' 类型的参数不可分配给类型参数...”?

这是因为value 被推断为字符串。 action2 只需要 foobar。因为string类型比foo | bar宽很多,TS报错

【讨论】:

【参考方案3】:

不要将 const 作为声明不可变变量的关键字(顺便说一下,在 JS 中相同)与称为 const assertions 的 as const 混淆。

Const 断言的行为根据类型略有不同(请参阅文档的附加链接),但在文字类型的情况下,它基本上意味着它不能扩展(或扩大)到string。它将它缩小到特定的文字类型,这向编译器发出不接受 string 的信号,这就是你得到的确切错误。

【讨论】:

以上是关于TypeScript const 和 const 与 as const的主要内容,如果未能解决你的问题,请参考以下文章

typescript Var,Let和const

Typescript const枚举问题

是否可以在 Typescript 中迭代 const 枚举?

在 TypeScript 中动态访问 const 对象字面量

如何从 url 获取 json 数据并将其保存到 const 变量 [TypeScript]

TypeScript 静态类型 const