【问题标题】:Typescript initialization of an empty array空数组的打字稿初始化
【发布时间】:2020-05-18 16:18:49
【问题描述】:

我有一个这样定义的 promises 数组。

export type PromisesArray = [
  Promise<IApplicant> | null,
  Promise<ICampaign | ICampaignLight> | null,
  Promise<IApplication[]> | null,
  Promise<IComment[]> | null,
  Promise<{ status: number; message: IActionTag[] }> | null,
  Promise<IHistoryEntry[]> | null,
  Promise<IDocs> | null,
  Promise<IForm> | null,
];

我想像const promisesArray = &lt;PromisesArray&gt;[]这样初始化为一个空值。

但是,我遇到了以下错误:

Conversion of type '[]' to type 'PromisesArray' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type '[]' is missing the following properties from type '[Promise<IApplicant>, Promise<ICampaign | ICampaignLight>, Promise<IApplication[]>, ... 4 more ..., Promise<...>]': 0, 1, 2, 3, and 4 more.ts(2352)

然后我像这样在数组中推送一些项目:

if (this._printOptions[EPrintOption.Tags]) {
  const applicantActionsTagsPromise = ApplicantService.getActions(this._applicantId);
  promisesArray.push(applicantActionsTagsPromise); // On this line
} else {
  promisesArray.push(null);
}

然后遇到这个错误。

Argument of type 'Promise<IActionTag[]>' is not assignable to parameter of type 'Promise<IApplicant> | Promise<ICampaign | ICampaignLight> | Promise<IApplication[]> | ... 4 more ... | Promise<...>'.
  Type 'Promise<IActionTag[]>' is not assignable to type 'Promise<IApplicant>'.
    Type 'IActionTag[]' is missing the following properties from type 'IApplicant': address, advertiseid, applicantid, birthdate, and 14 more.ts(2345)

我想在不使用any 类型运行的情况下解决这个问题。

【问题讨论】:

  • ApplicantService.getActions(this._applicantId); 返回什么?它似乎返回了 Promise&lt;IActionTag[]&gt;,这不是您的类型所允许的类型之一。
  • 您可能需要考虑将您的数组声明为type PromisesArray = Promise&lt;IApplicant | ICampaign | ICampaignLight | IApplication[] | ...&gt;[]; That would make working with the array easier

标签: javascript typescript promise


【解决方案1】:

这应该可以解决您在这两种情况下的问题。它必须如此复杂,因为您一次只将一个元素推入数组,而不是一次分配整个数组。如果您要更改代码以便同时分配整个 Promise 数组,那么您可以毫无问题地使用原始定义:

export type PromisesArray = []
  | [
    Promise<IApplicant> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null,
    Promise<IDocs> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null,
    Promise<IDocs> | null,
    Promise<IForm> | null
  ]
;

【讨论】:

  • 使用您的代码,我得到这种错误模式:每次我尝试在数组中插入一些东西
【解决方案2】:

我认为这个解决方案有两个问题:

首先,您的类型定义了一个可以包含 null 值的数组,而不是 undefined 值。

所以要获得正确的初始值,您应该使用:

const promisesArray = <PromisesArray>[null, null, null, null, null, null, null, null];

其次,Array.push 不知道您当前所处的索引,因此它无法帮助您推断该特定数组元素的正确类型。

一种解决方案是一次声明整个数组as const。这将允许 TypeScript 将您的数组视为一个元组。每个元素都有自己的类型,而不是所有类型的联合。

enum Tags {
    String,
    Number,
    Boolean
}

type Options = {
    [key in Tags]?: boolean;
};

const options: Options = {
    [Tags.String]: true,
    [Tags.Boolean]: true
};

// Use `as const` to infer the type of the array as a tuple. 
const promiseArray1 = [
    options[Tags.Number] ? Promise.resolve(5) : null,
    options[Tags.Boolean] ? Promise.resolve(true) : null,
    options[Tags.String] ? Promise.resolve('string') : null
] as const;

// Alternatively declare the type as you did before.
type PromiseArray = [
    Promise<number> | null,
    Promise<boolean> | null,
    Promise<string> | null
];
const promiseArray2: PromiseArray = [
    options[Tags.Number] ? Promise.resolve(5) : null,
    options[Tags.Boolean] ? Promise.resolve(true) : null,
    options[Tags.String] ? Promise.resolve('string') : null
];

Playground

【讨论】:

  • 即使我将类型更改为包含未定义,我也不能像我发布的那样声明我的箭头:将类型“[]”转换为类型“PromisesArray”可能是一个错误,因为这两种类型都没有充分重叠与另一个。如果这是故意的,请先将表达式转换为“未知”。类型“[]”缺少类型“[Promise, Promise, Promise, ... 4 more ..., Promise<...>]': 0, 1, 2, 3, and 4 more.ts(2352)
  • 为您添加了一个可能的解决方案
  • 我认为我的代码不够详细会导致误解。我创建了一个 codepen 以使我的代码示例更清晰,而不是在此处粘贴我的整个代码:codepen.io/theolavaux/pen/ExVOMLQ?editors=0010
  • 我检查了笔,但我仍然认为同样的逻辑适用。与其做多个 if 语句并一个一个地推送项目,不如通过内联条件一次创建你的 Promise 列表。
【解决方案3】:

如果你最终定义了一个数组类型,每个位置都有如此特殊的类型。也许使用数组根本不是最好的选择。 如果您定义具有以下命名属性的类型,您似乎会受益:

interface MyPromisesBundle {
  promiseIApplicant?: Promise<IApplicant>;
  promiseICampaign?: Promise<ICampaign>;
  ...
}

【讨论】:

    猜你喜欢
    • 2018-06-01
    • 1970-01-01
    • 2020-08-18
    • 2017-11-16
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多