Skip to content

Commit cb855af

Browse files
committed
Fix bug in checker that created zero length intersections, try constraint based types
1 parent 988e5a4 commit cb855af

File tree

2 files changed

+78
-10
lines changed

2 files changed

+78
-10
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7951,6 +7951,15 @@ namespace ts {
79517951
typeSet.push(type);
79527952
}
79537953
}
7954+
// cases for the non-strict null and undefined - if, for example, the interection is _just_ null and/or undefined
7955+
else if (flags & TypeFlags.Nullable) {
7956+
if (flags & TypeFlags.Null) {
7957+
includes |= TypeIncludes.Null
7958+
}
7959+
if (flags & TypeFlags.Undefined) {
7960+
includes |= TypeIncludes.Undefined;
7961+
}
7962+
}
79547963
return includes;
79557964
}
79567965

@@ -7988,6 +7997,14 @@ namespace ts {
79887997
if (includes & TypeIncludes.EmptyObject && !(includes & TypeIncludes.ObjectType)) {
79897998
typeSet.push(emptyObjectType);
79907999
}
8000+
if (typeSet.length === 0) {
8001+
if (includes & TypeIncludes.Null) {
8002+
typeSet.push(nullType);
8003+
}
8004+
if (includes & TypeIncludes.Undefined) {
8005+
typeSet.push(undefinedType);
8006+
}
8007+
}
79918008
if (typeSet.length === 1) {
79928009
return typeSet[0];
79938010
}
@@ -7999,6 +8016,7 @@ namespace ts {
79998016
return getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
80008017
UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
80018018
}
8019+
Debug.assert(typeSet.length > 1, "Intersection type must have more than one member");
80028020
const id = getTypeListId(typeSet);
80038021
let type = intersectionTypes.get(id);
80048022
if (!type) {

src/lib/es5.d.ts

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,35 +1361,85 @@ type Extract<T, U> = T extends U ? T : never;
13611361
type NonNullable<T> = T extends null | undefined ? never : T;
13621362

13631363
declare namespace TypeFacts {
1364+
/**
1365+
* Effectively replaces a `T` with a `T extends string`
1366+
*/
1367+
export type IsString<T extends string> = T;
1368+
1369+
/**
1370+
* Effectively replaces a `T` with a `T extends number`
1371+
*/
1372+
export type IsNumber<T extends number> = T;
1373+
1374+
/**
1375+
* Effectively replaces a `T` with a `T extends boolean`
1376+
*/
1377+
export type IsBoolean<T extends boolean> = T;
1378+
1379+
/**
1380+
* Effectively replaces a `T` with a `T extends symbol`
1381+
*/
1382+
export type IsSymbol<T extends symbol> = T;
1383+
1384+
/**
1385+
* Effectively replaces a `T` with a `T extends object`
1386+
*/
1387+
export type IsObject<T extends object> = T;
1388+
1389+
/**
1390+
* Effectively replaces a `T` with a `T extends (...args: any[]) => any`
1391+
*/
1392+
export type IsFunction<T extends (...args: any[]) => any> = T;
1393+
1394+
/**
1395+
* Effectively replaces a `T` with a `T extends undefined | void`
1396+
*/
1397+
export type IsUndefined<T extends undefined | void> = T;
1398+
1399+
/**
1400+
* Effectively replaces a `T` with a `T extends null`
1401+
*/
1402+
export type IsNull<T extends null> = T;
1403+
1404+
/**
1405+
* Effectively replaces a `T` with a `T extends undefined | null | void`
1406+
*/
1407+
export type IsUndefinedOrNull<T extends undefined | null | void> = T;
1408+
1409+
/**
1410+
* Effectively replaces a `T` with a `T extends false | null | undefined | void | 0 | ""`
1411+
*/
1412+
export type IsFalsy<T extends false | null | undefined | void | 0 | ""> = T;
1413+
13641414
/**
13651415
* Include only string from T
13661416
*/
1367-
export type EQString<T> = T extends string ? T : never;
1417+
export type EQString<T> = T extends IsString<infer U> ? T&U : never;
13681418

13691419
/**
13701420
* Include only number from T
13711421
*/
1372-
export type EQNumber<T> = T extends number ? T : never;
1422+
export type EQNumber<T> = T extends IsNumber<infer U> ? T&U : never;
13731423

13741424
/**
13751425
* Include only boolean from T
13761426
*/
1377-
export type EQBoolean<T> = T extends boolean ? T : never;
1427+
export type EQBoolean<T> = T extends IsBoolean<infer U> ? T&U : never;
13781428

13791429
/**
13801430
* Include only symbol from T
13811431
*/
1382-
export type EQSymbol<T> = T extends symbol ? T : never;
1432+
export type EQSymbol<T> = T extends IsSymbol<infer U> ? T&U : never;
13831433

13841434
/**
13851435
* Include only object from T
13861436
*/
1387-
export type EQObject<T> = T extends object ? T : never;
1437+
export type EQObject<T> = T extends IsObject<infer U> ? T&U : never;
13881438

13891439
/**
13901440
* Include only functions from T
13911441
*/
1392-
export type EQFunction<T> = T extends (...args: any[]) => any ? T : never;
1442+
export type EQFunction<T> = T extends IsFunction<infer U> ? T&U : never;
13931443

13941444
/**
13951445
* Exclude only string from T
@@ -1424,17 +1474,17 @@ declare namespace TypeFacts {
14241474
/**
14251475
* Include only undefined from T
14261476
*/
1427-
export type EQUndefined<T> = T extends undefined | void ? T : never;
1477+
export type EQUndefined<T> = T extends IsUndefined<infer U> ? T&U : never;
14281478

14291479
/**
14301480
* Include only null from T
14311481
*/
1432-
export type EQNull<T> = T extends null ? T : never;
1482+
export type EQNull<T> = T extends IsNull<infer U> ? T&U : never;
14331483

14341484
/**
14351485
* Include only null and undefined from T
14361486
*/
1437-
export type EQUndefinedOrNull<T> = T extends null | undefined | void ? T : never;
1487+
export type EQUndefinedOrNull<T> = T extends IsUndefinedOrNull<infer U> ? T&U : never;
14381488

14391489
/**
14401490
* Exclude only undefined from T
@@ -1459,7 +1509,7 @@ declare namespace TypeFacts {
14591509
/**
14601510
* Include falsy from T
14611511
*/
1462-
export type Falsy<T> = T extends false | null | undefined | void | 0 | "" ? T : never;
1512+
export type Falsy<T> = T extends IsFalsy<infer U> ? T&U : never;
14631513
}
14641514

14651515
/**

0 commit comments

Comments
 (0)