繁体   English   中英

如何使用 TypeScript 中的额外属性初始化数组 object?

[英]How to initialize an array object with extra properties in TypeScript?

我需要创建以下类型的 object:

type ArrayWithA = [number, number, number] & { a: string };

我这样做如下:

const obj : any = [1, 2, 3];
obj.a = "foo";
const arrayWithA : ArrayWithA = obj as ArrayWithA;

问题:有什么更好的方法来完成这个(即不使用any )?

奖励问题:什么是初始化 object 类型的好方法: type FuncWithA = ((string)=>void) & { a: string }

使用Object.assign

Object.assign的返回类型只是其 arguments 类型的交集,因此您可以通过列出它们的部分并立即组合来组合这些混合对象,而不是事后添加额外的属性(这通常需要类型转换,正如你所注意到的)。

因此,对于您的一些示例,您可能会这样做:

type ArrayWithA = [number, number, number] & { a: string };

// Try like so:
// The cast is needed as otherwise it will be inferred as number[].
const obj2 = Object.assign([1, 2, 3] as [number, number, number], {a: "foo"}); // obj2 has type: [number, number, number] & { a: string } and is assignable to ArrayWithA.

// Same for functions!
type FuncWithA = ((arg: string) => void) & { a: string };

const f1 = Object.assign((s: string) => {}, {a: "foo"}) // f1 has type: ((s: string) => void) & { a: string } and is assignable to FuncWithA.

游乐场链接。

我建议使用Object.assign()TypeScript 的标准库将其表示为返回所需形式的交集类型。 有一点问题是,要让编译器仅仅推断出数组文字将是确切类型的元组[number, number, number]并不容易。 如果您对readonly [number, number, number]没问题,那么您可以使用const断言

type ArrayWithA = readonly [number, number, number] & { a: string };
const arrayWithA: ArrayWithA = Object.assign([1, 2, 3] as const, { a: "foo" });

否则,您可以使用各种技巧:

type ArrayWithA = [number, number, number] & { a: string };

const arr: [number, number, number] = [1, 2, 3]; // annotate extra variable
let arrayWithA: ArrayWithA = Object.assign(arr, { a: "foo" });

// type assertion
arrayWithA = Object.assign([1, 2, 3] as [number, number, number], { a: "foo" });

// helper function
const asTuple = <T extends any[]>(arr: [...T]) => arr;
arrayWithA = Object.assign(asTuple([1, 2, 3]), { a: "foo" });

对于函数,你可以用Object.assign()做同样的事情:

type FuncWithA = ((x: string) => void) & { a: string }
let funcWithA: FuncWithA = Object.assign(
  (x: string) => console.log(x.toUpperCase()), 
  { a: "foo" }
);

但是您也可以只使用 function 语句并稍后添加属性,因为 TypeScript 3.1 引入了expando 函数

function func(x: string) {
    console.log(x);
}
func.a = "foo"; // no error
funcWithA = func; // that works

Playground 代码链接

我会 go 类似:

type ArrayWithA = [number, number, number] & { a: string };
namespace ArrayWithA {
  export function of(a: string, ...rest: [number, number, number]): ArrayWithA {
    const o = rest as ArrayWithA;
    o.a = a;
    return o;
  }
}

const arrayWithA = ArrayWithA.of('a', 1, 2, 3);

暂无
暂无

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

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