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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…