TypeScript:键入带有值或空的数组/元组

TypeScript: Typing array / tuple with values or empty

我正在尝试输入自定义 React 挂钩:

import { useRef } from 'react';

type Reference = [
  Promise<unknown>,
  (value?: unknown) => void,
  (reason?: unknown) => void,
];

const usePromise = () => {
  const reference: Reference = [];
  const container = useRef(reference);

  reference[0] = new Promise((resolve, reject) => {
    reference[1] = resolve;
    reference[2] = reject;
  });

  // [promise, resolve, reject]
  return container.current;
};

export default usePromise;

TypeScript 抱怨 reference 说:

Type '[]' is not assignable to type 'Reference'.
  Source has 0 element(s) but target requires 3.

如何让 TypeScript 也接受空数组/元组初始化?而且也许还有一种方法可以给 usePromise 值的类型,这样它就不会说 unknown?

编辑 2:

如果要将元组初始化为空数组,可以这样做:

const reference : [Reference, Reference, Reference] = ([] as unknown) as [Reference, Reference, Reference];

编辑:根据 OP 的评论编辑

如果你想使用元组,你需要做这样的事情: 请阅读下面的内联评论。

type Reference = {
    name:  string;
    age: number;
}

//In your case, it should be something like this beause your tuple may have upto 3 values of type Reference.

//initialization
//null! - the '!' mark after null is the non-null assertion operator, which will let you assign null value to a type Reference.
const reference2: [Reference, Reference, Reference] = [null!, null!, null!];
//assignment
reference2[0] = {name: 'John', age:10};

原答案: 那是因为你已经声明了一个 const 变量 reference,它是 Reference 类型([=44= 的对象实例],类型或接口称为 Reference),但是用一个空数组 [ ].

如果您希望 reference 拥有 Reference 个对象的数组,那么您应该改为这样做:

const reference: Reference[] = []; 

如果您在 tsconfig 中启用了严格的类型检查,您应该这样做:

const reference: Reference[] = [] as Reference[];

您可以在此处阅读有关 as 关键字的信息:

类型 Reference 是一个包含三个条目的元组。因此,当您分配给 Reference 类型的变量时,打字稿会检查 1) 分配的值是否为元组 2) 分配的元组是否具有所需的长度 3) 元组中的所有类型是否匹配Reference 类型中对应的类型。

您指定了一个空列表,这违反了这些条件。如果您没有启用严格的空检查,您可以简单地分配 const reference: Reference = [null, null, null];

而不是强制打字稿忽略你的问题,我觉得描述 reference 的真实情况更好:

let reference: Reference|null = null;

或者:

type Reference = [
  Promise<unknown> | null,
  ((value?: unknown) => void) | null,
  ((reason?: unknown) => void) | null,
];