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