Skip to content

Commit

Permalink
Lazified instantiation of union/intersection types featuring a mapped…
Browse files Browse the repository at this point in the history
… type
  • Loading branch information
gcnew committed Jul 27, 2017
1 parent d82fd60 commit 73c78e6
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7588,7 +7588,7 @@ namespace ts {
// eagerly using the constraint type of 'this' at the given location.
if (maybeTypeOfKind(indexType, TypeFlags.TypeVariable | TypeFlags.Index) ||
maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) ||
isGenericMappedType(objectType)) {
maybeTypeOfKind(objectType, isGenericMappedType)) {
if (objectType.flags & TypeFlags.Any) {
return objectType;
}
Expand Down Expand Up @@ -16976,14 +16976,18 @@ namespace ts {

// Return true if type might be of the given kind. A union or intersection type might be of a given
// kind if at least one constituent type is of the given kind.
function maybeTypeOfKind(type: Type, kind: TypeFlags): boolean {
if (type.flags & kind) {
function maybeTypeOfKind(type: Type, kindOrPred: TypeFlags | ((x: Type) => boolean)): boolean {
const pred = typeof kindOrPred === 'number'
? (t: Type) => (t.flags & kindOrPred) !== 0
: kindOrPred;

if (pred(type)) {
return true;
}
if (type.flags & TypeFlags.UnionOrIntersection) {
const types = (<UnionOrIntersectionType>type).types;
for (const t of types) {
if (maybeTypeOfKind(t, kind)) {
if (maybeTypeOfKind(t, pred)) {
return true;
}
}
Expand Down
20 changes: 20 additions & 0 deletions tests/cases/conformance/types/mapped/mappedTypesIntersection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @strictNullChecks: true
// @declaration: true

type A<T> = ObjectHasKey<T, '0'>

type StringContains<S extends string, L extends string> = ({ [K in S]: 'true' } & {
[key: string]: 'false'
})[L]

type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>


type A1<T> = {
true: 'true'
false: 'false'
}[ObjectHasKey<T, '1'>]

type B = ObjectHasKey<[string, number], '1'> // B = "true"
type C = A<[string]> // C = "false"
type E = A1<[string]>

0 comments on commit 73c78e6

Please sign in to comment.