Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider inferences between mapped type templates lower priority #44126

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/compiler/checker.ts
Expand Up @@ -21718,12 +21718,14 @@ namespace ts {
}

function inferFromIndexTypes(source: Type, target: Type) {
// Inferences across mapped type index signatures are pretty much the same a inferences to homomorphic variables
const priority = (getObjectFlags(source) & getObjectFlags(target) & ObjectFlags.Mapped) ? InferencePriority.HomomorphicMappedType : 0;
const targetStringIndexType = getIndexTypeOfType(target, IndexKind.String);
if (targetStringIndexType) {
const sourceIndexType = getIndexTypeOfType(source, IndexKind.String) ||
getImplicitIndexTypeOfType(source, IndexKind.String);
if (sourceIndexType) {
inferFromTypes(sourceIndexType, targetStringIndexType);
inferWithPriority(sourceIndexType, targetStringIndexType, priority);
}
}
const targetNumberIndexType = getIndexTypeOfType(target, IndexKind.Number);
Expand All @@ -21732,7 +21734,7 @@ namespace ts {
getIndexTypeOfType(source, IndexKind.String) ||
getImplicitIndexTypeOfType(source, IndexKind.Number);
if (sourceIndexType) {
inferFromTypes(sourceIndexType, targetNumberIndexType);
inferWithPriority(sourceIndexType, targetNumberIndexType, priority);
}
}
}
Expand Down
58 changes: 58 additions & 0 deletions tests/baselines/reference/localTypeParameterInferencePriority.js
@@ -0,0 +1,58 @@
//// [localTypeParameterInferencePriority.ts]
export type UnrollOnHover<O extends object> = O extends object ?
{ [K in keyof O]: O[K]; } :
never;


export type Schema = Record<string, unknown>;
class Table<S extends Schema> {
__schema!: S;

// Removing this line, removes the error
getRows<C extends keyof S>(): Array<UnrollOnHover<Pick<S, C>>> {
return null!
}
}

class ColumnSelectViewImp<S extends Schema> extends Table<S> { }


const ColumnSelectView1: new <S extends Schema>() => Table<UnrollOnHover<S>> = ColumnSelectViewImp;
const ColumnSelectView2: new <S extends Schema>() => Table<UnrollOnHover<S>> = Table;

//// [localTypeParameterInferencePriority.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Table = /** @class */ (function () {
function Table() {
}
// Removing this line, removes the error
Table.prototype.getRows = function () {
return null;
};
return Table;
}());
var ColumnSelectViewImp = /** @class */ (function (_super) {
__extends(ColumnSelectViewImp, _super);
function ColumnSelectViewImp() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ColumnSelectViewImp;
}(Table));
var ColumnSelectView1 = ColumnSelectViewImp;
var ColumnSelectView2 = Table;
@@ -0,0 +1,69 @@
=== tests/cases/compiler/localTypeParameterInferencePriority.ts ===
export type UnrollOnHover<O extends object> = O extends object ?
>UnrollOnHover : Symbol(UnrollOnHover, Decl(localTypeParameterInferencePriority.ts, 0, 0))
>O : Symbol(O, Decl(localTypeParameterInferencePriority.ts, 0, 26))
>O : Symbol(O, Decl(localTypeParameterInferencePriority.ts, 0, 26))

{ [K in keyof O]: O[K]; } :
>K : Symbol(K, Decl(localTypeParameterInferencePriority.ts, 1, 7))
>O : Symbol(O, Decl(localTypeParameterInferencePriority.ts, 0, 26))
>O : Symbol(O, Decl(localTypeParameterInferencePriority.ts, 0, 26))
>K : Symbol(K, Decl(localTypeParameterInferencePriority.ts, 1, 7))

never;


export type Schema = Record<string, unknown>;
>Schema : Symbol(Schema, Decl(localTypeParameterInferencePriority.ts, 2, 10))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

class Table<S extends Schema> {
>Table : Symbol(Table, Decl(localTypeParameterInferencePriority.ts, 5, 45))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 6, 12))
>Schema : Symbol(Schema, Decl(localTypeParameterInferencePriority.ts, 2, 10))

__schema!: S;
>__schema : Symbol(Table.__schema, Decl(localTypeParameterInferencePriority.ts, 6, 32))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 6, 12))

// Removing this line, removes the error
getRows<C extends keyof S>(): Array<UnrollOnHover<Pick<S, C>>> {
>getRows : Symbol(Table.getRows, Decl(localTypeParameterInferencePriority.ts, 7, 17))
>C : Symbol(C, Decl(localTypeParameterInferencePriority.ts, 10, 12))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 6, 12))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>UnrollOnHover : Symbol(UnrollOnHover, Decl(localTypeParameterInferencePriority.ts, 0, 0))
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 6, 12))
>C : Symbol(C, Decl(localTypeParameterInferencePriority.ts, 10, 12))

return null!
}
}

class ColumnSelectViewImp<S extends Schema> extends Table<S> { }
>ColumnSelectViewImp : Symbol(ColumnSelectViewImp, Decl(localTypeParameterInferencePriority.ts, 13, 1))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 15, 26))
>Schema : Symbol(Schema, Decl(localTypeParameterInferencePriority.ts, 2, 10))
>Table : Symbol(Table, Decl(localTypeParameterInferencePriority.ts, 5, 45))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 15, 26))


const ColumnSelectView1: new <S extends Schema>() => Table<UnrollOnHover<S>> = ColumnSelectViewImp;
>ColumnSelectView1 : Symbol(ColumnSelectView1, Decl(localTypeParameterInferencePriority.ts, 18, 5))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 18, 30))
>Schema : Symbol(Schema, Decl(localTypeParameterInferencePriority.ts, 2, 10))
>Table : Symbol(Table, Decl(localTypeParameterInferencePriority.ts, 5, 45))
>UnrollOnHover : Symbol(UnrollOnHover, Decl(localTypeParameterInferencePriority.ts, 0, 0))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 18, 30))
>ColumnSelectViewImp : Symbol(ColumnSelectViewImp, Decl(localTypeParameterInferencePriority.ts, 13, 1))

const ColumnSelectView2: new <S extends Schema>() => Table<UnrollOnHover<S>> = Table;
>ColumnSelectView2 : Symbol(ColumnSelectView2, Decl(localTypeParameterInferencePriority.ts, 19, 5))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 19, 30))
>Schema : Symbol(Schema, Decl(localTypeParameterInferencePriority.ts, 2, 10))
>Table : Symbol(Table, Decl(localTypeParameterInferencePriority.ts, 5, 45))
>UnrollOnHover : Symbol(UnrollOnHover, Decl(localTypeParameterInferencePriority.ts, 0, 0))
>S : Symbol(S, Decl(localTypeParameterInferencePriority.ts, 19, 30))
>Table : Symbol(Table, Decl(localTypeParameterInferencePriority.ts, 5, 45))

@@ -0,0 +1,40 @@
=== tests/cases/compiler/localTypeParameterInferencePriority.ts ===
export type UnrollOnHover<O extends object> = O extends object ?
>UnrollOnHover : UnrollOnHover<O>

{ [K in keyof O]: O[K]; } :
never;


export type Schema = Record<string, unknown>;
>Schema : Schema

class Table<S extends Schema> {
>Table : Table<S>

__schema!: S;
>__schema : S

// Removing this line, removes the error
getRows<C extends keyof S>(): Array<UnrollOnHover<Pick<S, C>>> {
>getRows : <C extends keyof S>() => Array<UnrollOnHover<Pick<S, C>>>

return null!
>null! : null
>null : null
}
}

class ColumnSelectViewImp<S extends Schema> extends Table<S> { }
>ColumnSelectViewImp : ColumnSelectViewImp<S>
>Table : Table<S>


const ColumnSelectView1: new <S extends Schema>() => Table<UnrollOnHover<S>> = ColumnSelectViewImp;
>ColumnSelectView1 : new <S extends Schema>() => Table<UnrollOnHover<S>>
>ColumnSelectViewImp : typeof ColumnSelectViewImp

const ColumnSelectView2: new <S extends Schema>() => Table<UnrollOnHover<S>> = Table;
>ColumnSelectView2 : new <S extends Schema>() => Table<UnrollOnHover<S>>
>Table : typeof Table

20 changes: 20 additions & 0 deletions tests/cases/compiler/localTypeParameterInferencePriority.ts
@@ -0,0 +1,20 @@
export type UnrollOnHover<O extends object> = O extends object ?
{ [K in keyof O]: O[K]; } :
never;


export type Schema = Record<string, unknown>;
class Table<S extends Schema> {
__schema!: S;

// Removing this line, removes the error
getRows<C extends keyof S>(): Array<UnrollOnHover<Pick<S, C>>> {
return null!
}
}

class ColumnSelectViewImp<S extends Schema> extends Table<S> { }


const ColumnSelectView1: new <S extends Schema>() => Table<UnrollOnHover<S>> = ColumnSelectViewImp;
const ColumnSelectView2: new <S extends Schema>() => Table<UnrollOnHover<S>> = Table;