Open
Description
Search Terms
non-aliasing types
Suggestion
I would like an "officially blessed" way to tell TS if it should give me a type alias, or give me an "expanded" type. (See examples)
Now that this issue has been fixed,
#32824
the technique I've been using to force TS to not alias a type will break when I migrate to TS 3.6/3.7
Use Cases
In some cases, seeing Mapped1<T>/Intersected1<T>/Unioned1<T>
is better for a developer (see examples).
In other cases, seeing the full "expanded" type is better (see examples for Mapped2<T>/Intersected2<T>/Unioned2<T>
)
Examples
type Identity<T> = T;
type Mapped1<T> = { [k in keyof T]: [T[k], "mapped"] };
type Mapped2<T> = Identity<{ [k in keyof T]: [T[k], "mapped"] }>;
declare function foo1(): Mapped1<{ x: string, y: number }>;
declare function foo2(): Mapped2<{ x: string, y: number }>;
/*
Aliased, bad
const m1: Mapped1<{
x: string;
y: number;
}>
*/
const m1 = foo1();
/*
Non-aliased, good
const m2: {
x: [string, "mapped"];
y: [number, "mapped"];
}
*/
const m2 = foo2();
//==============================================================
type Intersected1<T> = T & { hi: string };
type Intersected2<T> = Identity<T & { hi: string }>;
declare function bar1(): Intersected1<{ x: string, y: number }>;
declare function bar2(): Intersected2<{ x: string, y: number }>;
/*
const i1: Intersected1<{
x: string;
y: number;
}>
*/
const i1 = bar1();
/*
const i2: {
x: string;
y: number;
} & {
hi: string;
}
*/
const i2 = bar2();
//==============================================================
type Unioned1<T> = T | { hi: string };
type Unioned2<T> = Identity<T | { hi: string }>;
declare function baz1(): Unioned1<{ x: string, y: number }>;
declare function baz2(): Unioned2<{ x: string, y: number }>;
/*
const u1: Unioned1<{
x: string;
y: number;
}>
*/
const u1 = baz1();
/*
const u2: {
hi: string;
} | {
x: string;
y: number;
}
*/
const u2 = baz2();
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
Related
@weswigham brought up a different way to force TS to not alias a type.
I prefer my Identity<T>
trick because it doesn't create a new "temporary" object type.