Skip to content

Commit

Permalink
Add assignability rule relaxing the assignability of partial mapped t…
Browse files Browse the repository at this point in the history
…ypes (#30112)

* Add assignability rule relaxing the assignability of partial mapped types

* Update comment
  • Loading branch information
weswigham authored Mar 8, 2019
1 parent 45a6cb7 commit 58e847a
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 8 deletions.
26 changes: 18 additions & 8 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12725,16 +12725,26 @@ namespace ts {
(<IndexedAccessType>template).indexType === getTypeParameterFromMappedType(target)) {
return Ternary.True;
}
// A source type T is related to a target type { [P in Q]: X } if Q is related to keyof T and T[Q] is related to X.
if (!isGenericMappedType(source) && isRelatedTo(getConstraintTypeFromMappedType(target), getIndexType(source))) {
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target));
const templateType = getTemplateTypeFromMappedType(target);
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
return result;
if (!isGenericMappedType(source)) {
const targetConstraint = getConstraintTypeFromMappedType(target);
const sourceKeys = getIndexType(source);
const hasOptionalUnionKeys = modifiers & MappedTypeModifiers.IncludeOptional && targetConstraint.flags & TypeFlags.Union;
const filteredByApplicability = hasOptionalUnionKeys ? filterType(targetConstraint, t => !!isRelatedTo(t, sourceKeys)) : undefined;
// A source type T is related to a target type { [P in Q]: X } if Q is related to keyof T and T[Q] is related to X.
// A source type T is related to a target type { [P in Q]?: X } if some constituent Q' of Q is related to keyof T and T[Q'] is related to X.
if (hasOptionalUnionKeys
? !(filteredByApplicability!.flags & TypeFlags.Never)
: isRelatedTo(targetConstraint, sourceKeys)) {
const indexingType = hasOptionalUnionKeys ? filteredByApplicability! : getTypeParameterFromMappedType(target);
const indexedAccessType = getIndexedAccessType(source, indexingType);
const templateType = getTemplateTypeFromMappedType(target);
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
return result;
}
}
originalErrorInfo = errorInfo;
errorInfo = saveErrorInfo;
}
originalErrorInfo = errorInfo;
errorInfo = saveErrorInfo;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [mappedTypePartialNonHomomorphicBaseConstraint.ts]
export type Errors<D> = { readonly [K in keyof D | "base"]?: string[] };

class Model<D> {
getErrors(): Errors<D> {
return { base: ["some base error"] };
}
}


//// [mappedTypePartialNonHomomorphicBaseConstraint.js]
"use strict";
exports.__esModule = true;
var Model = /** @class */ (function () {
function Model() {
}
Model.prototype.getErrors = function () {
return { base: ["some base error"] };
};
return Model;
}());
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
=== tests/cases/compiler/mappedTypePartialNonHomomorphicBaseConstraint.ts ===
export type Errors<D> = { readonly [K in keyof D | "base"]?: string[] };
>Errors : Symbol(Errors, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 0))
>D : Symbol(D, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 19))
>K : Symbol(K, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 36))
>D : Symbol(D, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 19))

class Model<D> {
>Model : Symbol(Model, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 72))
>D : Symbol(D, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 2, 12))

getErrors(): Errors<D> {
>getErrors : Symbol(Model.getErrors, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 2, 16))
>Errors : Symbol(Errors, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 0, 0))
>D : Symbol(D, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 2, 12))

return { base: ["some base error"] };
>base : Symbol(base, Decl(mappedTypePartialNonHomomorphicBaseConstraint.ts, 4, 12))
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
=== tests/cases/compiler/mappedTypePartialNonHomomorphicBaseConstraint.ts ===
export type Errors<D> = { readonly [K in keyof D | "base"]?: string[] };
>Errors : Errors<D>

class Model<D> {
>Model : Model<D>

getErrors(): Errors<D> {
>getErrors : () => Errors<D>

return { base: ["some base error"] };
>{ base: ["some base error"] } : { base: string[]; }
>base : string[]
>["some base error"] : string[]
>"some base error" : "some base error"
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type Errors<D> = { readonly [K in keyof D | "base"]?: string[] };

class Model<D> {
getErrors(): Errors<D> {
return { base: ["some base error"] };
}
}

0 comments on commit 58e847a

Please sign in to comment.