简体   繁体   English

为什么TypeScript不接受这个任务?

[英]Why TypeScript will not accept this assignment?

I am trying to define a type that could be A, B, or an object with a key that can contains as value an array or 2 or more items that themselves can be A, or B or such list object (so that the definition is recursive).我正在尝试定义一个可以是 A、B 或 object 的类型,其键可以包含一个数组或 2 个或多个本身可以是 A、B 或此类列表 object 的项目作为值(因此定义是递归)。

This is what I came up with:这就是我想出的:

type A = {
    prop1: string;
}

type B = {
    prop2: number;
}

type Array = {
    list: [AorB, AorB, ...AorB[]]
}

type AorB = A | B | Array;

type AorBorArray = AorB;

If I use it for something that is just A or B, it works fine:如果我将它用于只是 A 或 B 的东西,它可以正常工作:

const obj1 = { prop1: 'test' };
const a: A = obj1; // OK

const obj2 = { prop2: 123 };
const b: B = obj2;    // OK

However, if I attempt to assign a list to a variable of type AorBorArray , or fails:但是,如果我尝试将列表分配给AorBorArray类型的变量,或者失败:

const list = {
    list: [
        {prop1: 'test'},
        {prop2: 123}
    ]
};

const assignTest: AorBorArray = list; // Error

在此处输入图像描述

It only works if I cast that list variable to AorBorArray explicitly:仅当我将该list变量显式转换为AorBorArray时它才有效:

const list = {
    list: [
        {prop1: 'test'},
        {prop2: 123}
    ]
} as AorBorArray;

const assignTest: AorBorArray = list; // OK

If I change the Array type to:如果我将Array类型更改为:

type Array = {
    list: AorB[]
}

it also works.它也有效。 But I'd like to require 2 or more items in that array.但我想在该数组中需要 2 个或更多项目。

Why is this?为什么是这样? Users will provide this object, so I don't want them to have to cast every time.用户将提供这个 object,所以我不希望他们每次都必须投射。 How can I fix the typings so that the assignment just works?我怎样才能修复打字,使作业正常工作?

Thanks!谢谢!

When you assign to a new const without a type annotation, then typescript does its best to assume the type.当您分配给没有类型注释的新const时,typescript 会尽力假定该类型。

In this case:在这种情况下:

const list = {
    list: [
        {prop1: 'test'},
        {prop2: 123}
    ]
};

The type becomes:类型变为:

const list: {
    list: ({
        prop1: string;
        prop2?: undefined;
    } | {
        prop2: number;
        prop1?: undefined;
    })[];
}

That means that the array can have any number items that either have a prop1 or a prop2 .这意味着该数组可以包含任意数量的具有prop1prop2的项目。

At this point it has no way of knowing that you actually want a tuple type like [AorB, AorB, ...AorB[]] .在这一点上,它无法知道您实际上想要一个像[AorB, AorB, ...AorB[]]这样的元组类型。

Then you try to assign this to AorBorArray and it the array doesn't match the tuple.然后您尝试将其分配给AorBorArray并且该数组与元组不匹配。

This is typically solved in two ways.这通常通过两种方式解决。


  1. Annotate the variable with the right type when it's created.在创建变量时使用正确的类型对其进行注释。
const list: AorBorArray = {
    list: [
        {prop1: 'test'},
        {prop2: 123}
    ]
};

const assignTest: AorBorArray = list; // fine

Now typescript knows how the interpret the array literal, and validates as a tuple type.现在 typescript 知道如何解释数组文字,并验证为元组类型。


  1. Use as const to force a non mutable interpretation of the array, which yields a tuple type since the length in known.使用as const强制对数组进行非可变解释,这会产生一个元组类型,因为长度已知。

But first you have to make sure your type accept an immutable value, which may or may not be right for your use case.但首先你必须确保你的类型接受一个不可变的值,这可能适合也可能不适合你的用例。

type MyArray = {
    list: readonly [AorB, AorB, ...AorB[]]
}

And now:现在:

const list = {
    list: [
        {prop1: 'test'},
        {prop2: 123}
    ]
} as const;

const assignTest: AorBorArray = list; // fine

Most Typescript developers will know to be careful with arrays when a tuple type is expected.大多数 Typescript 开发人员都知道在需要元组类型时要小心 arrays。 But this is usually a non issue, since if you pass an array literal directly to a function that requires a tuple, it will be interpreted as a tuple and there's no problem.但这通常不是问题,因为如果您将数组文字直接传递给需要元组的 function ,它将被解释为元组并且没有问题。

The only problem comes when you try to create the value separately first, without a type annotation, and then pass it a function later.唯一的问题是,您先尝试单独创建值,不使用类型注释,然后稍后将其传递给 function。 And in those cases you quickly learn to look up what type is expected, import it, and annotate your value with it as in option 1.在这些情况下,您很快就会学会查找预期的类型,导入它,并用它来注释您的值,如选项 1 中所示。

So I wouldn't worry about too much.所以我不会担心太多。

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

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