Add assignability rule relaxing the assignability of partial mapped types (#30112)

* Add assignability rule relaxing the assignability of partial mapped types

* Update comment
This commit is contained in:
Wesley Wigham 2019-03-08 14:01:27 -08:00 committed by GitHub
parent 45a6cb7066
commit 58e847abb5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 8 deletions

View file

@ -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;
}
}

View file

@ -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;
}());

View file

@ -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))
}
}

View file

@ -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"
}
}

View file

@ -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"] };
}
}