Skip to content

Commit

Permalink
Use homomorphic templated type for Omit
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Jan 27, 2021
1 parent 203a5ce commit 743f49a
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 28 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17925,7 +17925,7 @@ namespace ts {
}
}
}
else if (isGenericMappedType(target) && !target.declaration.nameType) {
else if (isGenericMappedType(target) && (!target.declaration.nameType || relation === comparableRelation)) {
// A source type T is related to a target type { [P in X]: T[P] }
const template = getTemplateTypeFromMappedType(target);
const modifiers = getMappedTypeModifiers(target);
Expand All @@ -17935,7 +17935,7 @@ namespace ts {
return Ternary.True;
}
if (!isGenericMappedType(source)) {
const targetConstraint = getConstraintTypeFromMappedType(target);
const targetConstraint = relation === comparableRelation ? getNameTypeFromMappedType(target) || getConstraintTypeFromMappedType(target) : getConstraintTypeFromMappedType(target);
const sourceKeys = getIndexType(source, /*stringsOnly*/ undefined, /*noIndexSignatures*/ true);
const includeOptional = modifiers & MappedTypeModifiers.IncludeOptional;
const filteredByApplicability = includeOptional ? intersectTypes(targetConstraint, sourceKeys) : undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1493,7 +1493,7 @@ type Extract<T, U> = T extends U ? T : never;
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type Omit<T, K extends keyof any> = {[_K in keyof T as Exclude<_K, K>]: T[_K]};

/**
* Exclude null and undefined from T
Expand Down
13 changes: 13 additions & 0 deletions tests/baselines/reference/omitOfTypeExtendingIndexSignature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//// [omitOfTypeExtendingIndexSignature.ts]
// #36981
type AnyRecord = Record<string, any>;
interface ExtendsAny extends AnyRecord {
myKey1: string;
myKey2: string;
}

type OmitsKey = Omit<ExtendsAny, "myKey2">;
type OmitsKey1 = OmitsKey["myKey1"]; // should be `string`
type OmitsKey2 = OmitsKey["myKey2"]; // should be `any`

//// [omitOfTypeExtendingIndexSignature.js]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
=== tests/cases/compiler/omitOfTypeExtendingIndexSignature.ts ===
// #36981
type AnyRecord = Record<string, any>;
>AnyRecord : Symbol(AnyRecord, Decl(omitOfTypeExtendingIndexSignature.ts, 0, 0))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

interface ExtendsAny extends AnyRecord {
>ExtendsAny : Symbol(ExtendsAny, Decl(omitOfTypeExtendingIndexSignature.ts, 1, 37))
>AnyRecord : Symbol(AnyRecord, Decl(omitOfTypeExtendingIndexSignature.ts, 0, 0))

myKey1: string;
>myKey1 : Symbol(ExtendsAny.myKey1, Decl(omitOfTypeExtendingIndexSignature.ts, 2, 40))

myKey2: string;
>myKey2 : Symbol(ExtendsAny.myKey2, Decl(omitOfTypeExtendingIndexSignature.ts, 3, 19))
}

type OmitsKey = Omit<ExtendsAny, "myKey2">;
>OmitsKey : Symbol(OmitsKey, Decl(omitOfTypeExtendingIndexSignature.ts, 5, 1))
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
>ExtendsAny : Symbol(ExtendsAny, Decl(omitOfTypeExtendingIndexSignature.ts, 1, 37))

type OmitsKey1 = OmitsKey["myKey1"]; // should be `string`
>OmitsKey1 : Symbol(OmitsKey1, Decl(omitOfTypeExtendingIndexSignature.ts, 7, 43))
>OmitsKey : Symbol(OmitsKey, Decl(omitOfTypeExtendingIndexSignature.ts, 5, 1))

type OmitsKey2 = OmitsKey["myKey2"]; // should be `any`
>OmitsKey2 : Symbol(OmitsKey2, Decl(omitOfTypeExtendingIndexSignature.ts, 8, 36))
>OmitsKey : Symbol(OmitsKey, Decl(omitOfTypeExtendingIndexSignature.ts, 5, 1))

22 changes: 22 additions & 0 deletions tests/baselines/reference/omitOfTypeExtendingIndexSignature.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
=== tests/cases/compiler/omitOfTypeExtendingIndexSignature.ts ===
// #36981
type AnyRecord = Record<string, any>;
>AnyRecord : AnyRecord

interface ExtendsAny extends AnyRecord {
myKey1: string;
>myKey1 : string

myKey2: string;
>myKey2 : string
}

type OmitsKey = Omit<ExtendsAny, "myKey2">;
>OmitsKey : Omit<ExtendsAny, "myKey2">

type OmitsKey1 = OmitsKey["myKey1"]; // should be `string`
>OmitsKey1 : string

type OmitsKey2 = OmitsKey["myKey2"]; // should be `any`
>OmitsKey2 : any

18 changes: 9 additions & 9 deletions tests/baselines/reference/omitTypeHelperModifiers01.types
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,55 @@ type A = {
};

type B = Omit<A, 'a'>;
>B : B
>B : Omit<A, "a">

function f(x: B) {
>f : (x: B) => void
>x : B
>x : Omit<A, "a">

const b = x.b;
>b : string | undefined
>x.b : string | undefined
>x : B
>x : Omit<A, "a">
>b : string | undefined

x.b = "hello";
>x.b = "hello" : "hello"
>x.b : string | undefined
>x : B
>x : Omit<A, "a">
>b : string | undefined
>"hello" : "hello"

x.b = undefined;
>x.b = undefined : undefined
>x.b : string | undefined
>x : B
>x : Omit<A, "a">
>b : string | undefined
>undefined : undefined

const c = x.c;
>c : boolean
>x.c : boolean
>x : B
>x : Omit<A, "a">
>c : boolean

x.c = true;
>x.c = true : true
>x.c : any
>x : B
>x : Omit<A, "a">
>c : any
>true : true

const d = x.d;
>d : unknown
>x.d : unknown
>x : B
>x : Omit<A, "a">
>d : unknown

x.d = d;
>x.d = d : unknown
>x.d : unknown
>x : B
>x : Omit<A, "a">
>d : unknown
>d : unknown
}
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/omitTypeTestErrors01.errors.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tests/cases/compiler/omitTypeTestErrors01.ts(11,16): error TS2339: Property 'c' does not exist on type 'Bar'.
tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' does not exist on type 'Baz'.
tests/cases/compiler/omitTypeTestErrors01.ts(11,16): error TS2339: Property 'c' does not exist on type 'Omit<Foo, "c">'.
tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' does not exist on type 'Omit<Foo, "c" | "b">'.


==== tests/cases/compiler/omitTypeTestErrors01.ts (2 errors) ====
Expand All @@ -15,13 +15,13 @@ tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b'
export function getBarC(bar: Bar) {
return bar.c;
~
!!! error TS2339: Property 'c' does not exist on type 'Bar'.
!!! error TS2339: Property 'c' does not exist on type 'Omit<Foo, "c">'.
}

export function getBazB(baz: Baz) {
return baz.b;
~
!!! error TS2339: Property 'b' does not exist on type 'Baz'.
!!! error TS2339: Property 'b' does not exist on type 'Omit<Foo, "c" | "b">'.
}


12 changes: 6 additions & 6 deletions tests/baselines/reference/omitTypeTestErrors01.types
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,28 @@ interface Foo {
}

export type Bar = Omit<Foo, "c">;
>Bar : Bar
>Bar : Omit<Foo, "c">

export type Baz = Omit<Foo, "b" | "c">;
>Baz : Baz
>Baz : Omit<Foo, "c" | "b">

export function getBarC(bar: Bar) {
>getBarC : (bar: Bar) => any
>bar : Bar
>bar : Omit<Foo, "c">

return bar.c;
>bar.c : any
>bar : Bar
>bar : Omit<Foo, "c">
>c : any
}

export function getBazB(baz: Baz) {
>getBazB : (baz: Baz) => any
>baz : Baz
>baz : Omit<Foo, "c" | "b">

return baz.b;
>baz.b : any
>baz : Baz
>baz : Omit<Foo, "c" | "b">
>b : any
}

Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/omitTypeTests01.types
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,28 @@ interface Foo {
}

export type Bar = Omit<Foo, "c">;
>Bar : Bar
>Bar : Omit<Foo, "c">

export type Baz = Omit<Foo, "b" | "c">;
>Baz : Baz
>Baz : Omit<Foo, "c" | "b">

export function getBarA(bar: Bar) {
>getBarA : (bar: Bar) => string
>bar : Bar
>bar : Omit<Foo, "c">

return bar.a;
>bar.a : string
>bar : Bar
>bar : Omit<Foo, "c">
>a : string
}

export function getBazA(baz: Baz) {
>getBazA : (baz: Baz) => string
>baz : Baz
>baz : Omit<Foo, "c" | "b">

return baz.a;
>baz.a : string
>baz : Baz
>baz : Omit<Foo, "c" | "b">
>a : string
}

Expand Down
10 changes: 10 additions & 0 deletions tests/cases/compiler/omitOfTypeExtendingIndexSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// #36981
type AnyRecord = Record<string, any>;
interface ExtendsAny extends AnyRecord {
myKey1: string;
myKey2: string;
}

type OmitsKey = Omit<ExtendsAny, "myKey2">;
type OmitsKey1 = OmitsKey["myKey1"]; // should be `string`
type OmitsKey2 = OmitsKey["myKey2"]; // should be `any`

0 comments on commit 743f49a

Please sign in to comment.