简体   繁体   English

TypeScript const 和 const 与 as const

[英]TypeScript const and const with as const

To the best of my understanding TypeScript views a const string variable as an immutable typed variable with only that value and no other possible value.据我了解,TypeScript 将const string变量视为只有该值而没有其他可能值的不可变类型变量。 I always thought that adding as const to that was redundant.我一直认为添加as const是多余的。

Why am I getting the following in the 2nd part of the example?为什么我在示例的第二部分得到以下内容?

Argument of type 'string' is not assignable to parameter of type... “字符串”类型的参数不能分配给类型参数...

Example:例子:

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. 上面的游乐场样本在这里。

Don't confuse const as a keyword for declaring immutable variables (same in JS by the way) with as const , which called const assertions .不要将const作为声明不可变变量的关键字(顺便说一句,在 JS 中相同)与as const混淆,后者称为const assertions

Const assertions behaves slightly different depending on the type (see attached link to the documentation), but in case of literal types it basically means that it cannot be extended (or widened) to string . const 断言的行为根据类型略有不同(请参阅文档的附加链接),但对于文字类型,它基本上意味着它不能扩展(或扩大)到string It narrows it to that specific literal type, which signals to compiler not to accept string and this is the exact error you are getting.它将它缩小到特定的文字类型,这向编译器发出不接受string的信号,这就是你得到的确切错误。

To the best of my understanding TypeScript views a const string variable as an immutable typed variable with only that value and no other possible value.据我了解,TypeScript 将 const 字符串变量视为只有该值而没有其他可能值的不可变类型变量。 I always thought that adding "as const" to that was redundant.我一直认为在其中添加“as const”是多余的。

Why am I getting "Argument of type 'string' is not assignable to parameter of type..." in the second part of the example?为什么在示例的第二部分中出现“'string' 类型的参数不可分配给类型参数...”?

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. 上面的游乐场样本在这里。

Even if the first part of your question (with as const) does not warn about any error, it still does not work as each method is not compiled to javascript code and therefore the execution fails.即使您的问题的第一部分(使用 as const)没有警告任何错误,它仍然不起作用,因为each方法都没有编译为 javascript 代码,因此执行失败。

Although your example tries to address an issue with how const behaves during narrowing I think it is too complicated.尽管您的示例试图解决 const 在缩小期间的行为问题,但我认为它太复杂了。 You probably will find useful the following suggestion issue on typescript project您可能会发现有关 typescript 项目的以下建议问题很有用

Support Const Type Constraint支持 Const 类型约束

TS is able to infer all types. TS 能够推断所有类型。 You just should give a little bit of love ))) Just add extra generics to help TS figure out all types.你应该给予一点爱))) 只需添加额外的 generics 以帮助 TS 找出所有类型。 TS is smart enough to figure out that const foo='FOO' is constant even without as const . TS 足够聪明, const foo='FOO'即使没有as const也是常数。

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

As you see, I added extra U and V generics.如您所见,我添加了额外的 U 和 V generics。

Please keep in mind, if you can't infer some type, try to add more generics )) This rule works 80% of time )请记住,如果您无法推断出某种类型,请尝试添加更多 generics ))这条规则在 80% 的时间内都有效)

Playground 操场

Why am I getting "Argument of type 'string' is not assignable to parameter of type..." in the second part of the example?为什么在示例的第二部分中出现“'string' 类型的参数不可分配给类型参数...”?

This is because value is infered to string.这是因为value被推断为字符串。 action2 expects only foo or bar . action2只需要foobar Because string type is much wider than foo | bar因为string类型比foo | bar宽得多。 foo | bar , TS complains foo | bar ,TS抱怨

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM