Skip to content

Commit

Permalink
Merge pull request #31374 from weswigham/defer-conditionals-with-simp…
Browse files Browse the repository at this point in the history
…lification

Simplify conditionals upon comparison, rather than instantiation
  • Loading branch information
ahejlsberg committed May 13, 2019
2 parents bb9c5c9 + 8ba53b6 commit 4e040f7
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 192 deletions.
36 changes: 32 additions & 4 deletions src/compiler/checker.ts
Expand Up @@ -9044,7 +9044,7 @@ namespace ts {
}

function getSubstitutionType(typeVariable: TypeVariable, substitute: Type) {
if (substitute.flags & TypeFlags.AnyOrUnknown) {
if (substitute.flags & TypeFlags.AnyOrUnknown || substitute === typeVariable) {
return typeVariable;
}
const id = `${getTypeId(typeVariable)}>${getTypeId(substitute)}`;
Expand Down Expand Up @@ -10194,7 +10194,9 @@ namespace ts {
}

function getSimplifiedType(type: Type, writing: boolean): Type {
return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(<IndexedAccessType>type, writing) : type;
return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(<IndexedAccessType>type, writing) :
type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(<ConditionalType>type, writing) :
type;
}

function distributeIndexOverObjectType(objectType: Type, indexType: Type, writing: boolean) {
Expand Down Expand Up @@ -10257,6 +10259,32 @@ namespace ts {
return type[cache] = type;
}

function getSimplifiedConditionalType(type: ConditionalType, writing: boolean) {
const falseType = getFalseTypeFromConditionalType(type);
const trueType = getTrueTypeFromConditionalType(type);
const checkType = type.checkType;
const extendsType = type.extendsType;
// Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`.
if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) {
if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
return getSimplifiedType(trueType, writing);
}
else if (isIntersectionEmpty(checkType, extendsType)) { // Always false
return neverType;
}
}
else if (trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) {
if (!(checkType.flags & TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
return neverType;
}
else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false
return getSimplifiedType(falseType, writing);
}
}

return type;
}

function substituteIndexedMappedType(objectType: MappedType, index: Type) {
const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]);
const templateMapper = combineTypeMappers(objectType.mapper, mapper);
Expand Down Expand Up @@ -12431,10 +12459,10 @@ namespace ts {
if (target.flags & TypeFlags.Substitution) {
target = (<SubstitutionType>target).typeVariable;
}
if (source.flags & TypeFlags.IndexedAccess) {
if (source.flags & TypeFlags.Simplifiable) {
source = getSimplifiedType(source, /*writing*/ false);
}
if (target.flags & TypeFlags.IndexedAccess) {
if (target.flags & TypeFlags.Simplifiable) {
target = getSimplifiedType(target, /*writing*/ true);
}

Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Expand Up @@ -3966,6 +3966,8 @@ namespace ts {
StructuredOrInstantiable = StructuredType | Instantiable,
/* @internal */
ObjectFlagsType = Nullable | Never | Object | Union | Intersection,
/* @internal */
Simplifiable = IndexedAccess | Conditional,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
Expand Down

0 comments on commit 4e040f7

Please sign in to comment.