类型'“ abc”'不能分配给类型'{length:3; }'

时间:2019-12-17 22:56:08

标签: typescript

我写了code

var x: { length: 3 } = "abc";

并且无法通过消息编译

  

类型'“ abc”'不能分配给类型'{length:3; }'。

但是字符串abc的长度肯定等于3。怎么了?


  

"abc"string,而{ length: 3 }是具有length属性的对象,该属性必须等于数字3,它们根本不相交。

但是this code是有效的:

var y: { length: number } = "abc";

所以似乎对象没有问题?

1 个答案:

答案 0 :(得分:3)

length相比,TypeScript目前对string literal typesnumber属性一无所知。对于字符串文字的任何字符的类型,也将不会是string的事实更加具体。在运行时,"abc".length将是3,但是编译器只知道它是number。在运行时,"abc"[1]将是"b",但是编译器只知道它是string

有一个open issue, microsoft/TypeScript#34692,,它表明字符串文字会自动缩小。如果您希望看到这种情况发生,则可能想去那里给它一个?或描述用例,如果您认为它特别令人信服。

如果出于某种原因,您需要为特定的字符串文字输入更具体的类型,则可以使用type assertion来将所需的期望值手动通知编译器,例如:

const x = "abc" as StringLiteral<"abc", ["a", "b", "c"]>;

const len = x.length; // const len: 3
console.log(len); // 3

const b = x.charAt(1).charAt(0)[0][0] // const b: StringLiteral<"b",["b"]>
console.log(b); // "b"

我的StringLiteral类型的定义如下

type StrToNum = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
type Rev<T extends Record<keyof T, keyof any>> = {
    [K in T[keyof T]]: { [P in keyof T]: T[P] extends K ? P : never }[keyof T]
};
type NumToStr = Rev<Pick<StrToNum, Exclude<keyof StrToNum, keyof any[]>>>;
type StringLiteral<T extends string, A extends string[] = [T]> =
    { [K in "length" | Exclude<keyof A, keyof any[]>]:
        A[K] extends string ? StringLiteral<A[K], [A[K]]> : A[K] } & {
            charAt<N extends keyof NumToStr>(
                pos: N
            ): StringLiteral<Extract<A[Extract<NumToStr[N], keyof A>], string>>
        } & T;

但是我无法想象值得付出努力。


好的,希望能有所帮助;祝你好运!

Link to code