Merge pull request #21156 from Microsoft/fix-diff-omit

Fix Diff and Omit
This commit is contained in:
Nathan Shively-Sanders
2018-01-12 16:10:37 -08:00
committed by GitHub
5 changed files with 183 additions and 17 deletions

View File

@@ -8359,30 +8359,45 @@ namespace ts {
return false;
}
function isMappedTypeToNever(type: Type) {
return getObjectFlags(type) & ObjectFlags.Mapped && getTemplateTypeFromMappedType(type as MappedType) === neverType;
}
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
// undefined if no transformation is possible.
function getSimplifiedIndexedAccessType(type: IndexedAccessType): Type {
const objectType = type.objectType;
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
// access types with default property values as expressed by D.
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType) && some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
const regularTypes: Type[] = [];
const stringIndexTypes: Type[] = [];
for (const t of (<IntersectionType>objectType).types) {
if (isStringIndexOnlyType(t)) {
stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String));
}
else {
regularTypes.push(t);
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) {
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
// access types with default property values as expressed by D.
if (some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
const regularTypes: Type[] = [];
const stringIndexTypes: Type[] = [];
for (const t of (<IntersectionType>objectType).types) {
if (isStringIndexOnlyType(t)) {
stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String));
}
else {
regularTypes.push(t);
}
}
return getUnionType([
getIndexedAccessType(getIntersectionType(regularTypes), type.indexType),
getIntersectionType(stringIndexTypes)
]);
}
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more mapped types with a template type `never`, '(U & V & { [P in T]: never })[K]', return a
// transformed type that removes the never-mapped type: '(U & V)[K]'. This mirrors what would happen
// eventually anyway, but it easier to reason about.
if (some((<IntersectionType>objectType).types, isMappedTypeToNever)) {
const nonNeverTypes = filter((<IntersectionType>objectType).types, t => !isMappedTypeToNever(t));
return getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType);
}
return getUnionType([
getIndexedAccessType(getIntersectionType(regularTypes), type.indexType),
getIntersectionType(stringIndexTypes)
]);
}
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
// construct the type Box<T[X]>.