Skip to content

Commit a3845a9

Browse files
committed
Optimize getTypeWithFacts
1 parent 24d8d84 commit a3845a9

1 file changed

Lines changed: 26 additions & 19 deletions

File tree

src/compiler/checker.ts

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7924,6 +7924,14 @@ namespace ts {
79247924
return result;
79257925
}
79267926

7927+
function isFunctionObjectType(type: ObjectType): boolean {
7928+
// We do a quick check for a "bind" property before performing the more expensive subtype
7929+
// check. This gives us a quicker out in the common case where an object type is not a function.
7930+
const resolved = resolveStructuredTypeMembers(type);
7931+
return !!(resolved.callSignatures.length || resolved.constructSignatures.length ||
7932+
hasProperty(resolved.members, "bind") && isTypeSubtypeOf(type, globalFunctionType));
7933+
}
7934+
79277935
function getTypeFacts(type: Type): TypeFacts {
79287936
const flags = type.flags;
79297937
if (flags & TypeFlags.String) {
@@ -7952,8 +7960,7 @@ namespace ts {
79527960
type === falseType ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
79537961
}
79547962
if (flags & TypeFlags.ObjectType) {
7955-
const resolved = resolveStructuredTypeMembers(type);
7956-
return resolved.callSignatures.length || resolved.constructSignatures.length || isTypeSubtypeOf(type, globalFunctionType) ?
7963+
return isFunctionObjectType(<ObjectType>type) ?
79577964
strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts :
79587965
strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
79597966
}
@@ -7980,23 +7987,23 @@ namespace ts {
79807987
if (!(type.flags & TypeFlags.Union)) {
79817988
return getTypeFacts(type) & include ? type : neverType;
79827989
}
7983-
let firstType: Type;
7984-
let types: Type[];
7985-
for (const t of (type as UnionType).types) {
7990+
const types = (<UnionType>type).types;
7991+
const length = types.length;
7992+
let i = 0;
7993+
while (i < length && getTypeFacts(types[i]) & include) i++;
7994+
if (i === length) {
7995+
return type;
7996+
}
7997+
const filtered = types.slice(0, i);
7998+
i++;
7999+
while (i < length) {
8000+
const t = types[i];
79868001
if (getTypeFacts(t) & include) {
7987-
if (!firstType) {
7988-
firstType = t;
7989-
}
7990-
else {
7991-
if (!types) {
7992-
types = [firstType];
7993-
}
7994-
types.push(t);
7995-
}
8002+
filtered.push(t);
79968003
}
8004+
i++;
79978005
}
7998-
return types ? getUnionType(types) :
7999-
firstType ? firstType : neverType;
8006+
return getUnionType(filtered);
80008007
}
80018008

80028009
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
@@ -8175,14 +8182,14 @@ namespace ts {
81758182
if (!(type.flags & TypeFlags.Union)) {
81768183
return f(type) ? type : neverType;
81778184
}
8178-
let types = (<UnionType>type).types;
8179-
let length = types.length;
8185+
const types = (<UnionType>type).types;
8186+
const length = types.length;
81808187
let i = 0;
81818188
while (i < length && f(types[i])) i++;
81828189
if (i === length) {
81838190
return type;
81848191
}
8185-
let filtered = types.slice(0, i);
8192+
const filtered = types.slice(0, i);
81868193
i++;
81878194
while (i < length) {
81888195
const t = types[i];

0 commit comments

Comments
 (0)