Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

typescript

I need to create an object of the following type:

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

I do this as follows:

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

Question: What is a better way to accomplish this (i.e. without using any)?

Bonus Question: What is a good way to initialize an object of type: type FuncWithA = ((string)=>void) & { a: string }?

like image 493
THX-1138 Avatar asked Jul 09 '26 06:07

THX-1138


1 Answers

I would recommend using Object.assign(), which TypeScript's standard library represents as returning an intersection type of the form you want. There's a little bit of a wrinkle in that it's not easy to get the compiler to just infer that an array literal will be a tuple of the exact type [number, number, number]. If you are okay with readonly [number, number, number] then you can use a const assertion:

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

Otherwise there are various tricks you can use:

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" });

For functions, you can do the same thing with Object.assign():

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

But you could also just use a function statement and add the property later, since TypeScript 3.1 introduced expando functions:

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

Playground link to code

like image 65
jcalz Avatar answered Jul 14 '26 15:07

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!