如何在 TypeScript 中使用额外属性初始化数组对象?
2021-01-12
142
我需要创建以下类型的对象:
type ArrayWithA = [number, number, number] & { a: string };
我按如下方式执行此操作:
const obj : any = [1, 2, 3];
obj.a = "foo";
const arrayWithA : ArrayWithA = obj as ArrayWithA;
问题:
有什么更好的方法可以实现此目的(即不使用
any
)?
附加问题:
有什么好方法可以初始化以下类型的对象:
type FuncWithA = ((string)=>void) & { a: string >
?
3个回答
我建议使用
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" }
);
但您也可以只使用函数语句,稍后再添加属性,因为 TypeScript 3.1 引入了 扩展函数 :
function func(x: string) {
console.log(x);
}
func.a = "foo"; // no error
funcWithA = func; // that works
jcalz
2021-01-12
使用
Object.assign
!
Object.assign
的返回类型只是其参数类型的交集,因此您可以通过列出它们的各部分并立即组合来组成这些混合对象,而不是事后添加其他属性(这通常需要类型转换,正如您所注意到的)。
因此,对于您的某些示例,您可以这样做:
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.
CRice
2021-01-12
我会选择类似这样的方法:
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);
Tomasz Gawel
2021-01-12