From a7c06d47fd289d6adb0afc5520a7825fa2fa4b3b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 11 Oct 2018 12:55:12 -0700 Subject: [PATCH 1/4] Measure variance of aliased conditional types using variance markers --- src/compiler/checker.ts | 146 +++--- src/compiler/types.ts | 2 + .../conditionalTypeDoesntSpinForever.js | 152 ++++++ .../conditionalTypeDoesntSpinForever.symbols | 489 ++++++++++++++++++ .../conditionalTypeDoesntSpinForever.types | 487 +++++++++++++++++ .../conditionalTypeDoesntSpinForever.ts | 119 +++++ 6 files changed, 1335 insertions(+), 60 deletions(-) create mode 100644 tests/baselines/reference/conditionalTypeDoesntSpinForever.js create mode 100644 tests/baselines/reference/conditionalTypeDoesntSpinForever.symbols create mode 100644 tests/baselines/reference/conditionalTypeDoesntSpinForever.types create mode 100644 tests/cases/compiler/conditionalTypeDoesntSpinForever.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bc93cce86b89f..d278a87177c34 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7598,35 +7598,35 @@ namespace ts { * @param typeParameters The requested type parameters. * @param minTypeArgumentCount The minimum number of required type arguments. */ - function fillMissingTypeArguments(typeArguments: Type[], typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[]; - function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined; - function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { + function fillMissingTypeArguments(typeArguments: ReadonlyArray, typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[]; + function fillMissingTypeArguments(typeArguments: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined; + function fillMissingTypeArguments(typeArguments: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { const numTypeParameters = length(typeParameters); - if (numTypeParameters) { - const numTypeArguments = length(typeArguments); - if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) { - if (!typeArguments) { - typeArguments = []; - } + if (!numTypeParameters) { + return []; + } + const numTypeArguments = length(typeArguments); + if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) { + const result = typeArguments ? typeArguments.slice() : []; - // Map an unsatisfied type parameter with a default type. - // If a type parameter does not have a default type, or if the default type - // is a forward reference, the empty object type is used. - for (let i = numTypeArguments; i < numTypeParameters; i++) { - typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny); - } - for (let i = numTypeArguments; i < numTypeParameters; i++) { - const mapper = createTypeMapper(typeParameters!, typeArguments); - let defaultType = getDefaultFromTypeParameter(typeParameters![i]); - if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) { - defaultType = anyType; - } - typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); + // Map an unsatisfied type parameter with a default type. + // If a type parameter does not have a default type, or if the default type + // is a forward reference, the empty object type is used. + for (let i = numTypeArguments; i < numTypeParameters; i++) { + result[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny); + } + for (let i = numTypeArguments; i < numTypeParameters; i++) { + const mapper = createTypeMapper(typeParameters!, result); + let defaultType = getDefaultFromTypeParameter(typeParameters![i]); + if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) { + defaultType = anyType; } - typeArguments.length = typeParameters!.length; + result[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); } + result.length = typeParameters!.length; + return result; } - return typeArguments; + return typeArguments && typeArguments.slice(); } function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature { @@ -8223,7 +8223,7 @@ namespace ts { return checkNoTypeArguments(node, symbol) ? type : errorType; } - function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[] | undefined): Type { + function getTypeAliasInstantiation(symbol: Symbol, typeArguments: ReadonlyArray | undefined): Type { const type = getDeclaredTypeOfSymbol(symbol); const links = getSymbolLinks(symbol); const typeParameters = links.typeParameters!; @@ -11726,9 +11726,7 @@ namespace ts { return result; } - function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, variances: Variance[], reportErrors: boolean): Ternary { - const sources = source.typeArguments || emptyArray; - const targets = target.typeArguments || emptyArray; + function typeArgumentsRelatedTo(sources: ReadonlyArray = emptyArray, targets: ReadonlyArray = emptyArray, variances: ReadonlyArray = emptyArray, reportErrors: boolean): Ternary { if (sources.length !== targets.length && relation === identityRelation) { return Ternary.False; } @@ -11986,6 +11984,14 @@ namespace ts { } else if (source.flags & TypeFlags.Conditional) { if (target.flags & TypeFlags.Conditional) { + if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && + !(getAliasArgumentsContainsMarker(source) || getAliasArgumentsContainsMarker(target))) { + const variances = getAliasVariances(source.aliasSymbol); + if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } + } // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, // and Y1 is related to Y2. @@ -12044,7 +12050,7 @@ namespace ts { // type references (which are intended by be compared structurally). Obtain the variance // information for the type parameters and relate the type arguments accordingly. const variances = getVariances((source).target); - if (result = typeArgumentsRelatedTo(source, target, variances, reportErrors)) { + if (result = typeArgumentsRelatedTo((source).typeArguments, (target).typeArguments, variances, reportErrors)) { return result; } // The type arguments did not relate appropriately, but it may be because we have no variance @@ -12552,48 +12558,68 @@ namespace ts { return result; } + function isMarkerType(type: Type) { + return type === markerSuperType || type === markerSubType || type === markerOtherType; + } + + function getAliasArgumentsContainsMarker(type: Type) { + if (!type.aliasSymbol || !type.aliasTypeArguments) { + return false; + } + if (type.aliasTypeArgumentsContainsMarker !== undefined) { + return type.aliasTypeArgumentsContainsMarker; + } + return type.aliasTypeArgumentsContainsMarker = some(type.aliasTypeArguments, isMarkerType); + } + + function getAliasVariances(symbol: Symbol) { + const links = getSymbolLinks(symbol); + return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)))); + } + // Return an array containing the variance of each type parameter. The variance is effectively // a digest of the type comparisons that occur for each type argument when instantiations of the // generic type are structurally compared. We infer the variance information by comparing // instantiations of the generic type for type arguments with known relations. The function // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function // has been invoked recursively for the given generic type. + function getVariancesWorker(typeParameters: ReadonlyArray = emptyArray, cache: TCache, createMarkerType: (input: TCache, param: TypeParameter, marker: Type) => Type): Variance[] { + let variances = cache.variances; + if (!variances) { + // The emptyArray singleton is used to signal a recursive invocation. + cache.variances = emptyArray; + variances = []; + for (const tp of typeParameters) { + // We first compare instantiations where the type parameter is replaced with + // marker types that have a known subtype relationship. From this we can infer + // invariance, covariance, contravariance or bivariance. + const typeWithSuper = createMarkerType(cache, tp, markerSuperType); + const typeWithSub = createMarkerType(cache, tp, markerSubType); + let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) | + (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0); + // If the instantiations appear to be related bivariantly it may be because the + // type parameter is independent (i.e. it isn't witnessed anywhere in the generic + // type). To determine this we compare instantiations where the type parameter is + // replaced with marker types that are known to be unrelated. + if (variance === Variance.Bivariant && isTypeAssignableTo(createMarkerType(cache, tp, markerOtherType), typeWithSuper)) { + variance = Variance.Independent; + } + variances.push(variance); + } + cache.variances = variances; + } + return variances; + } + function getVariances(type: GenericType): Variance[] { if (!strictFunctionTypes) { return emptyArray; } - const typeParameters = type.typeParameters || emptyArray; - let variances = type.variances; - if (!variances) { - if (type === globalArrayType || type === globalReadonlyArrayType) { - // Arrays are known to be covariant, no need to spend time computing this - variances = [Variance.Covariant]; - } - else { - // The emptyArray singleton is used to signal a recursive invocation. - type.variances = emptyArray; - variances = []; - for (const tp of typeParameters) { - // We first compare instantiations where the type parameter is replaced with - // marker types that have a known subtype relationship. From this we can infer - // invariance, covariance, contravariance or bivariance. - const typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType); - const typeWithSub = getMarkerTypeReference(type, tp, markerSubType); - let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) | - (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0); - // If the instantiations appear to be related bivariantly it may be because the - // type parameter is independent (i.e. it isn't witnessed anywhere in the generic - // type). To determine this we compare instantiations where the type parameter is - // replaced with marker types that are known to be unrelated. - if (variance === Variance.Bivariant && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) { - variance = Variance.Independent; - } - variances.push(variance); - } - } - type.variances = variances; + if (type === globalArrayType || type === globalReadonlyArrayType) { + // Arrays are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters) + return emptyArray; } - return variances; + return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference); } // Return true if the given type reference has a 'void' type argument for a covariant type parameter. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3bd103579f1b3..9625695f0c932 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3641,6 +3641,7 @@ namespace ts { originatingImport?: ImportDeclaration | ImportCall; // Import declaration which produced the symbol, present if the symbol is marked as uncallable but had call signatures in `resolveESModuleSymbol` lateSymbol?: Symbol; // Late-bound symbol for a computed property specifierCache?: Map; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings + variances?: Variance[]; // Alias symbol type argument variance cache } /* @internal */ @@ -3893,6 +3894,7 @@ namespace ts { pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any) aliasSymbol?: Symbol; // Alias associated with type aliasTypeArguments?: ReadonlyArray; // Alias type arguments (if any) + /* @internal */ aliasTypeArgumentsContainsMarker?: boolean; // Alias type arguments (if any) /* @internal */ wildcardInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type /* @internal */ diff --git a/tests/baselines/reference/conditionalTypeDoesntSpinForever.js b/tests/baselines/reference/conditionalTypeDoesntSpinForever.js new file mode 100644 index 0000000000000..144503ac94bbe --- /dev/null +++ b/tests/baselines/reference/conditionalTypeDoesntSpinForever.js @@ -0,0 +1,152 @@ +//// [conditionalTypeDoesntSpinForever.ts] +// A *self-contained* demonstration of the problem follows... +// Test this by running `tsc --target es6` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. + +export enum PubSubRecordIsStoredInRedisAsA { + redisHash = "redisHash", + jsonEncodedRedisString = "jsonEncodedRedisString" + } + + export interface PubSubRecord> { + name: NAME; + record: RECORD; + identifier: IDENTIFIER; + storedAs: PubSubRecordIsStoredInRedisAsA; + maxMsToWaitBeforePublishing: number; + } + + type NameFieldConstructor = + SO_FAR extends {name: any} ? {} : { + name: (t?: TYPE) => BuildPubSubRecordType + } + + const buildNameFieldConstructor = (soFar: SO_FAR) => ( + "name" in soFar ? {} : { + name: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType + } + ); + + type StoredAsConstructor = + SO_FAR extends {storedAs: any} ? {} : { + storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; + storedRedisHash: () => BuildPubSubRecordType; + } + + const buildStoredAsConstructor = (soFar: SO_FAR) => ( + "storedAs" in soFar ? {} : { + storedAsJsonEncodedRedisString: () => + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as + BuildPubSubRecordType, + storedAsRedisHash: () => + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as + BuildPubSubRecordType, + } + ); + + type IdentifierFieldConstructor = + SO_FAR extends {identifier: any} ? {} : + SO_FAR extends {record: any} ? { + identifier: >(t?: TYPE) => BuildPubSubRecordType + } : {} + + const buildIdentifierFieldConstructor = (soFar: SO_FAR) => ( + "identifier" in soFar || (!("record" in soFar)) ? {} : { + identifier: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType + } + ); + + type RecordFieldConstructor = + SO_FAR extends {record: any} ? {} : { + record: (t?: TYPE) => BuildPubSubRecordType + } + + const buildRecordFieldConstructor = (soFar: SO_FAR) => ( + "record" in soFar ? {} : { + record: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType + } + ); + + type MaxMsToWaitBeforePublishingFieldConstructor = + SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : { + maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType, + neverDelayPublishing: () => BuildPubSubRecordType, + } + + const buildMaxMsToWaitBeforePublishingFieldConstructor = (soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor => ( + "maxMsToWaitBeforePublishing" in soFar ? {} : { + maxMsToWaitBeforePublishing: (instance: number = 0) => + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, + neverDelayPublishing: () => + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, + } + ) as MaxMsToWaitBeforePublishingFieldConstructor; + + type TypeConstructor = + SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? { + type: SO_FAR, + fields: Set, + hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR + } : {} + + const buildType = (soFar: SO_FAR) => ( + "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { + type: soFar, + fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), + hasField: (fieldName: string | number | symbol) => fieldName in soFar + } + ); + + type BuildPubSubRecordType = + NameFieldConstructor & + IdentifierFieldConstructor & + RecordFieldConstructor & + StoredAsConstructor & // infinite loop goes away when you comment out this line + MaxMsToWaitBeforePublishingFieldConstructor & + TypeConstructor + + const buildPubSubRecordType = (soFar: SO_FAR) => Object.assign( + {}, + buildNameFieldConstructor(soFar), + buildIdentifierFieldConstructor(soFar), + buildRecordFieldConstructor(soFar), + buildStoredAsConstructor(soFar), + buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), + buildType(soFar) + ) as BuildPubSubRecordType; + const PubSubRecordType = buildPubSubRecordType({}); + +//// [conditionalTypeDoesntSpinForever.js] +// A *self-contained* demonstration of the problem follows... +// Test this by running `tsc --target es6` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. +export var PubSubRecordIsStoredInRedisAsA; +(function (PubSubRecordIsStoredInRedisAsA) { + PubSubRecordIsStoredInRedisAsA["redisHash"] = "redisHash"; + PubSubRecordIsStoredInRedisAsA["jsonEncodedRedisString"] = "jsonEncodedRedisString"; +})(PubSubRecordIsStoredInRedisAsA || (PubSubRecordIsStoredInRedisAsA = {})); +const buildNameFieldConstructor = (soFar) => ("name" in soFar ? {} : { + name: (instance = undefined) => buildPubSubRecordType(Object.assign({}, soFar, { name: instance })) +}); +const buildStoredAsConstructor = (soFar) => ("storedAs" in soFar ? {} : { + storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString })), + storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash })), +}); +const buildIdentifierFieldConstructor = (soFar) => ("identifier" in soFar || (!("record" in soFar)) ? {} : { + identifier: (instance = undefined) => buildPubSubRecordType(Object.assign({}, soFar, { identifier: instance })) +}); +const buildRecordFieldConstructor = (soFar) => ("record" in soFar ? {} : { + record: (instance = undefined) => buildPubSubRecordType(Object.assign({}, soFar, { record: instance })) +}); +const buildMaxMsToWaitBeforePublishingFieldConstructor = (soFar) => ("maxMsToWaitBeforePublishing" in soFar ? {} : { + maxMsToWaitBeforePublishing: (instance = 0) => buildPubSubRecordType(Object.assign({}, soFar, { maxMsToWaitBeforePublishing: instance })), + neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, { maxMsToWaitBeforePublishing: 0 })), +}); +const buildType = (soFar) => ("identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { + type: soFar, + fields: () => new Set(Object.keys(soFar)), + hasField: (fieldName) => fieldName in soFar +}); +const buildPubSubRecordType = (soFar) => Object.assign({}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar)); +const PubSubRecordType = buildPubSubRecordType({}); diff --git a/tests/baselines/reference/conditionalTypeDoesntSpinForever.symbols b/tests/baselines/reference/conditionalTypeDoesntSpinForever.symbols new file mode 100644 index 0000000000000..d21db8eb90d5f --- /dev/null +++ b/tests/baselines/reference/conditionalTypeDoesntSpinForever.symbols @@ -0,0 +1,489 @@ +=== tests/cases/compiler/conditionalTypeDoesntSpinForever.ts === +// A *self-contained* demonstration of the problem follows... +// Test this by running `tsc --target es6` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. + +export enum PubSubRecordIsStoredInRedisAsA { +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) + + redisHash = "redisHash", +>redisHash : Symbol(PubSubRecordIsStoredInRedisAsA.redisHash, Decl(conditionalTypeDoesntSpinForever.ts, 3, 44)) + + jsonEncodedRedisString = "jsonEncodedRedisString" +>jsonEncodedRedisString : Symbol(PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 4, 28)) + } + + export interface PubSubRecord> { +>PubSubRecord : Symbol(PubSubRecord, Decl(conditionalTypeDoesntSpinForever.ts, 6, 3)) +>NAME : Symbol(NAME, Decl(conditionalTypeDoesntSpinForever.ts, 8, 32)) +>RECORD : Symbol(RECORD, Decl(conditionalTypeDoesntSpinForever.ts, 8, 52)) +>IDENTIFIER : Symbol(IDENTIFIER, Decl(conditionalTypeDoesntSpinForever.ts, 8, 60)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>RECORD : Symbol(RECORD, Decl(conditionalTypeDoesntSpinForever.ts, 8, 52)) + + name: NAME; +>name : Symbol(PubSubRecord.name, Decl(conditionalTypeDoesntSpinForever.ts, 8, 98)) +>NAME : Symbol(NAME, Decl(conditionalTypeDoesntSpinForever.ts, 8, 32)) + + record: RECORD; +>record : Symbol(PubSubRecord.record, Decl(conditionalTypeDoesntSpinForever.ts, 9, 15)) +>RECORD : Symbol(RECORD, Decl(conditionalTypeDoesntSpinForever.ts, 8, 52)) + + identifier: IDENTIFIER; +>identifier : Symbol(PubSubRecord.identifier, Decl(conditionalTypeDoesntSpinForever.ts, 10, 19)) +>IDENTIFIER : Symbol(IDENTIFIER, Decl(conditionalTypeDoesntSpinForever.ts, 8, 60)) + + storedAs: PubSubRecordIsStoredInRedisAsA; +>storedAs : Symbol(PubSubRecord.storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 11, 27)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) + + maxMsToWaitBeforePublishing: number; +>maxMsToWaitBeforePublishing : Symbol(PubSubRecord.maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 12, 45)) + } + + type NameFieldConstructor = +>NameFieldConstructor : Symbol(NameFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 14, 3)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 16, 28)) + + SO_FAR extends {name: any} ? {} : { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 16, 28)) +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 17, 20)) + + name: (t?: TYPE) => BuildPubSubRecordType +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 17, 39)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 18, 13)) +>t : Symbol(t, Decl(conditionalTypeDoesntSpinForever.ts, 18, 19)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 18, 13)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 16, 28)) +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 18, 64)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 18, 13)) + } + + const buildNameFieldConstructor = (soFar: SO_FAR) => ( +>buildNameFieldConstructor : Symbol(buildNameFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 21, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 21, 37)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 21, 45)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 21, 37)) + + "name" in soFar ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 21, 45)) + + name: (instance: TYPE = undefined) => +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 22, 28)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 23, 13)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 23, 19)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 23, 13)) +>undefined : Symbol(undefined) + + buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 21, 45)) +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 24, 56)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 23, 19)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 23, 13)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 21, 37)) +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 24, 94)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 23, 13)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 21, 37)) +>name : Symbol(name, Decl(conditionalTypeDoesntSpinForever.ts, 24, 142)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 23, 13)) + } + ); + + type StoredAsConstructor = +>StoredAsConstructor : Symbol(StoredAsConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 26, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 28, 27)) + + SO_FAR extends {storedAs: any} ? {} : { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 28, 27)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 29, 20)) + + storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; +>storedAsJsonEncodedRedisString : Symbol(storedAsJsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 29, 43)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 28, 27)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 30, 76)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>jsonEncodedRedisString : Symbol(PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 4, 28)) + + storedRedisHash: () => BuildPubSubRecordType; +>storedRedisHash : Symbol(storedRedisHash, Decl(conditionalTypeDoesntSpinForever.ts, 30, 142)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 28, 27)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 31, 61)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>redisHash : Symbol(PubSubRecordIsStoredInRedisAsA.redisHash, Decl(conditionalTypeDoesntSpinForever.ts, 3, 44)) + } + + const buildStoredAsConstructor = (soFar: SO_FAR) => ( +>buildStoredAsConstructor : Symbol(buildStoredAsConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 34, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 34, 36)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 34, 44)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 34, 36)) + + "storedAs" in soFar ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 34, 44)) + + storedAsJsonEncodedRedisString: () => +>storedAsJsonEncodedRedisString : Symbol(storedAsJsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 35, 32)) + + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 34, 44)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 37, 56)) +>PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString : Symbol(PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 4, 28)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>jsonEncodedRedisString : Symbol(PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 4, 28)) + + BuildPubSubRecordType, +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 34, 36)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 38, 42)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>jsonEncodedRedisString : Symbol(PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString, Decl(conditionalTypeDoesntSpinForever.ts, 4, 28)) + + storedAsRedisHash: () => +>storedAsRedisHash : Symbol(storedAsRedisHash, Decl(conditionalTypeDoesntSpinForever.ts, 38, 108)) + + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 34, 44)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 40, 56)) +>PubSubRecordIsStoredInRedisAsA.redisHash : Symbol(PubSubRecordIsStoredInRedisAsA.redisHash, Decl(conditionalTypeDoesntSpinForever.ts, 3, 44)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>redisHash : Symbol(PubSubRecordIsStoredInRedisAsA.redisHash, Decl(conditionalTypeDoesntSpinForever.ts, 3, 44)) + + BuildPubSubRecordType, +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 34, 36)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 41, 42)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) +>redisHash : Symbol(PubSubRecordIsStoredInRedisAsA.redisHash, Decl(conditionalTypeDoesntSpinForever.ts, 3, 44)) + } + ); + + type IdentifierFieldConstructor = +>IdentifierFieldConstructor : Symbol(IdentifierFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 43, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 45, 34)) + + SO_FAR extends {identifier: any} ? {} : +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 45, 34)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 46, 20)) + + SO_FAR extends {record: any} ? { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 45, 34)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 47, 20)) + + identifier: >(t?: TYPE) => BuildPubSubRecordType +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 47, 36)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 48, 19)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 45, 34)) +>t : Symbol(t, Decl(conditionalTypeDoesntSpinForever.ts, 48, 59)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 48, 19)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 45, 34)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 48, 104)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 48, 19)) + + } : {} + + const buildIdentifierFieldConstructor = (soFar: SO_FAR) => ( +>buildIdentifierFieldConstructor : Symbol(buildIdentifierFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 51, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 51, 43)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 51, 51)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 51, 43)) + + "identifier" in soFar || (!("record" in soFar)) ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 51, 51)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 51, 51)) + + identifier: (instance: TYPE = undefined) => +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 52, 60)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 53, 19)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 53, 25)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 53, 19)) +>undefined : Symbol(undefined) + + buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 51, 51)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 54, 56)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 53, 25)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 53, 19)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 51, 43)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 54, 100)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 53, 19)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 51, 43)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 54, 154)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 53, 19)) + } + ); + + type RecordFieldConstructor = +>RecordFieldConstructor : Symbol(RecordFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 56, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 58, 30)) + + SO_FAR extends {record: any} ? {} : { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 58, 30)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 59, 20)) + + record: (t?: TYPE) => BuildPubSubRecordType +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 59, 41)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 60, 15)) +>t : Symbol(t, Decl(conditionalTypeDoesntSpinForever.ts, 60, 21)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 60, 15)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 58, 30)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 60, 66)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 60, 15)) + } + + const buildRecordFieldConstructor = (soFar: SO_FAR) => ( +>buildRecordFieldConstructor : Symbol(buildRecordFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 63, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 63, 39)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 63, 47)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 63, 39)) + + "record" in soFar ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 63, 47)) + + record: (instance: TYPE = undefined) => +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 64, 30)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 65, 15)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 65, 21)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 65, 15)) +>undefined : Symbol(undefined) + + buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 63, 47)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 66, 56)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 65, 21)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 65, 15)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 63, 39)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 66, 96)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 65, 15)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 63, 39)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 66, 146)) +>TYPE : Symbol(TYPE, Decl(conditionalTypeDoesntSpinForever.ts, 65, 15)) + } + ); + + type MaxMsToWaitBeforePublishingFieldConstructor = +>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 70, 51)) + + SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 70, 51)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 71, 20)) + + maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType, +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 71, 62)) +>t : Symbol(t, Decl(conditionalTypeDoesntSpinForever.ts, 72, 36)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 70, 51)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 72, 82)) + + neverDelayPublishing: () => BuildPubSubRecordType, +>neverDelayPublishing : Symbol(neverDelayPublishing, Decl(conditionalTypeDoesntSpinForever.ts, 72, 120)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 70, 51)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 73, 66)) + } + + const buildMaxMsToWaitBeforePublishingFieldConstructor = (soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor => ( +>buildMaxMsToWaitBeforePublishingFieldConstructor : Symbol(buildMaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 76, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 76, 68)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) +>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) + + "maxMsToWaitBeforePublishing" in soFar ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 76, 68)) + + maxMsToWaitBeforePublishing: (instance: number = 0) => +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 77, 51)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 78, 36)) + + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 76, 68)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 79, 56)) +>instance : Symbol(instance, Decl(conditionalTypeDoesntSpinForever.ts, 78, 36)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 79, 132)) + + neverDelayPublishing: () => +>neverDelayPublishing : Symbol(neverDelayPublishing, Decl(conditionalTypeDoesntSpinForever.ts, 79, 170)) + + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 76, 68)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 81, 56)) +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 81, 125)) + } + ) as MaxMsToWaitBeforePublishingFieldConstructor; +>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60)) + + type TypeConstructor = +>TypeConstructor : Symbol(TypeConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 83, 59)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 85, 23)) + + SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? { +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 85, 23)) +>identifier : Symbol(identifier, Decl(conditionalTypeDoesntSpinForever.ts, 86, 20)) +>record : Symbol(record, Decl(conditionalTypeDoesntSpinForever.ts, 86, 36)) +>maxMsToWaitBeforePublishing : Symbol(maxMsToWaitBeforePublishing, Decl(conditionalTypeDoesntSpinForever.ts, 86, 49)) +>storedAs : Symbol(storedAs, Decl(conditionalTypeDoesntSpinForever.ts, 86, 86)) +>PubSubRecordIsStoredInRedisAsA : Symbol(PubSubRecordIsStoredInRedisAsA, Decl(conditionalTypeDoesntSpinForever.ts, 0, 0)) + + type: SO_FAR, +>type : Symbol(type, Decl(conditionalTypeDoesntSpinForever.ts, 86, 132)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 85, 23)) + + fields: Set, +>fields : Symbol(fields, Decl(conditionalTypeDoesntSpinForever.ts, 87, 19)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 85, 23)) + + hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR +>hasField : Symbol(hasField, Decl(conditionalTypeDoesntSpinForever.ts, 88, 32)) +>fieldName : Symbol(fieldName, Decl(conditionalTypeDoesntSpinForever.ts, 89, 17)) +>fieldName : Symbol(fieldName, Decl(conditionalTypeDoesntSpinForever.ts, 89, 17)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 85, 23)) + + } : {} + + const buildType = (soFar: SO_FAR) => ( +>buildType : Symbol(buildType, Decl(conditionalTypeDoesntSpinForever.ts, 92, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 92, 21)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 92, 21)) + + "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) + + type: soFar, +>type : Symbol(type, Decl(conditionalTypeDoesntSpinForever.ts, 93, 142)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) + + fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), +>fields : Symbol(fields, Decl(conditionalTypeDoesntSpinForever.ts, 94, 18)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 92, 21)) + + hasField: (fieldName: string | number | symbol) => fieldName in soFar +>hasField : Symbol(hasField, Decl(conditionalTypeDoesntSpinForever.ts, 95, 68)) +>fieldName : Symbol(fieldName, Decl(conditionalTypeDoesntSpinForever.ts, 96, 17)) +>fieldName : Symbol(fieldName, Decl(conditionalTypeDoesntSpinForever.ts, 96, 17)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 92, 29)) + } + ); + + type BuildPubSubRecordType = +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + NameFieldConstructor & +>NameFieldConstructor : Symbol(NameFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 14, 3)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + IdentifierFieldConstructor & +>IdentifierFieldConstructor : Symbol(IdentifierFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 43, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + RecordFieldConstructor & +>RecordFieldConstructor : Symbol(RecordFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 56, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + StoredAsConstructor & // infinite loop goes away when you comment out this line +>StoredAsConstructor : Symbol(StoredAsConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 26, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + MaxMsToWaitBeforePublishingFieldConstructor & +>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + TypeConstructor +>TypeConstructor : Symbol(TypeConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 83, 59)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29)) + + const buildPubSubRecordType = (soFar: SO_FAR) => Object.assign( +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 108, 33)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 108, 33)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) + + {}, + buildNameFieldConstructor(soFar), +>buildNameFieldConstructor : Symbol(buildNameFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 21, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + buildIdentifierFieldConstructor(soFar), +>buildIdentifierFieldConstructor : Symbol(buildIdentifierFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 51, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + buildRecordFieldConstructor(soFar), +>buildRecordFieldConstructor : Symbol(buildRecordFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 63, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + buildStoredAsConstructor(soFar), +>buildStoredAsConstructor : Symbol(buildStoredAsConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 34, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), +>buildMaxMsToWaitBeforePublishingFieldConstructor : Symbol(buildMaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 76, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + buildType(soFar) +>buildType : Symbol(buildType, Decl(conditionalTypeDoesntSpinForever.ts, 92, 7)) +>soFar : Symbol(soFar, Decl(conditionalTypeDoesntSpinForever.ts, 108, 41)) + + ) as BuildPubSubRecordType; +>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4)) +>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 108, 33)) + + const PubSubRecordType = buildPubSubRecordType({}); +>PubSubRecordType : Symbol(PubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 117, 7)) +>buildPubSubRecordType : Symbol(buildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 108, 7)) + diff --git a/tests/baselines/reference/conditionalTypeDoesntSpinForever.types b/tests/baselines/reference/conditionalTypeDoesntSpinForever.types new file mode 100644 index 0000000000000..d4fe4bf48261b --- /dev/null +++ b/tests/baselines/reference/conditionalTypeDoesntSpinForever.types @@ -0,0 +1,487 @@ +=== tests/cases/compiler/conditionalTypeDoesntSpinForever.ts === +// A *self-contained* demonstration of the problem follows... +// Test this by running `tsc --target es6` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. + +export enum PubSubRecordIsStoredInRedisAsA { +>PubSubRecordIsStoredInRedisAsA : PubSubRecordIsStoredInRedisAsA + + redisHash = "redisHash", +>redisHash : PubSubRecordIsStoredInRedisAsA.redisHash +>"redisHash" : "redisHash" + + jsonEncodedRedisString = "jsonEncodedRedisString" +>jsonEncodedRedisString : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString +>"jsonEncodedRedisString" : "jsonEncodedRedisString" + } + + export interface PubSubRecord> { + name: NAME; +>name : NAME + + record: RECORD; +>record : RECORD + + identifier: IDENTIFIER; +>identifier : IDENTIFIER + + storedAs: PubSubRecordIsStoredInRedisAsA; +>storedAs : PubSubRecordIsStoredInRedisAsA + + maxMsToWaitBeforePublishing: number; +>maxMsToWaitBeforePublishing : number + } + + type NameFieldConstructor = +>NameFieldConstructor : NameFieldConstructor + + SO_FAR extends {name: any} ? {} : { +>name : any + + name: (t?: TYPE) => BuildPubSubRecordType +>name : (t?: TYPE) => BuildPubSubRecordType +>t : TYPE +>name : TYPE + } + + const buildNameFieldConstructor = (soFar: SO_FAR) => ( +>buildNameFieldConstructor : (soFar: SO_FAR) => { name?: undefined; } | { name: (instance?: TYPE) => BuildPubSubRecordType; } +>(soFar: SO_FAR) => ( "name" in soFar ? {} : { name: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType } ) : (soFar: SO_FAR) => { name?: undefined; } | { name: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR +>( "name" in soFar ? {} : { name: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType } ) : {} | { name: (instance?: TYPE) => BuildPubSubRecordType; } + + "name" in soFar ? {} : { +>"name" in soFar ? {} : { name: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType } : {} | { name: (instance?: TYPE) => BuildPubSubRecordType; } +>"name" in soFar : boolean +>"name" : "name" +>soFar : SO_FAR +>{} : {} +>{ name: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType } : { name: (instance?: TYPE) => BuildPubSubRecordType; } + + name: (instance: TYPE = undefined) => +>name : (instance?: TYPE) => BuildPubSubRecordType +>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType : (instance?: TYPE) => BuildPubSubRecordType +>instance : TYPE +>undefined : undefined + + buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE} : SO_FAR & { name: TYPE; } +>Object.assign({}, soFar, {name: instance as TYPE}) : SO_FAR & { name: TYPE; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{name: instance as TYPE} : { name: TYPE; } +>name : TYPE +>instance as TYPE : TYPE +>instance : TYPE +>name : TYPE +>name : TYPE + } + ); + + type StoredAsConstructor = +>StoredAsConstructor : StoredAsConstructor + + SO_FAR extends {storedAs: any} ? {} : { +>storedAs : any + + storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; +>storedAsJsonEncodedRedisString : () => BuildPubSubRecordType +>storedAs : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString +>PubSubRecordIsStoredInRedisAsA : any + + storedRedisHash: () => BuildPubSubRecordType; +>storedRedisHash : () => BuildPubSubRecordType +>storedAs : PubSubRecordIsStoredInRedisAsA.redisHash +>PubSubRecordIsStoredInRedisAsA : any + } + + const buildStoredAsConstructor = (soFar: SO_FAR) => ( +>buildStoredAsConstructor : (soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } +>(soFar: SO_FAR) => ( "storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType, } ) : (soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } +>soFar : SO_FAR +>( "storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType, } ) : {} | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } + + "storedAs" in soFar ? {} : { +>"storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType, } : {} | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } +>"storedAs" in soFar : boolean +>"storedAs" : "storedAs" +>soFar : SO_FAR +>{} : {} +>{ storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType, } : { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } + + storedAsJsonEncodedRedisString: () => +>storedAsJsonEncodedRedisString : () => BuildPubSubRecordType +>() => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType : () => BuildPubSubRecordType + + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as +>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}) : SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString} : { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; } +>storedAs : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString +>PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString +>PubSubRecordIsStoredInRedisAsA : typeof PubSubRecordIsStoredInRedisAsA +>jsonEncodedRedisString : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString + + BuildPubSubRecordType, +>storedAs : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString +>PubSubRecordIsStoredInRedisAsA : any + + storedAsRedisHash: () => +>storedAsRedisHash : () => BuildPubSubRecordType +>() => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType : () => BuildPubSubRecordType + + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as +>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}) : SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{storedAs: PubSubRecordIsStoredInRedisAsA.redisHash} : { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; } +>storedAs : PubSubRecordIsStoredInRedisAsA.redisHash +>PubSubRecordIsStoredInRedisAsA.redisHash : PubSubRecordIsStoredInRedisAsA.redisHash +>PubSubRecordIsStoredInRedisAsA : typeof PubSubRecordIsStoredInRedisAsA +>redisHash : PubSubRecordIsStoredInRedisAsA.redisHash + + BuildPubSubRecordType, +>storedAs : PubSubRecordIsStoredInRedisAsA.redisHash +>PubSubRecordIsStoredInRedisAsA : any + } + ); + + type IdentifierFieldConstructor = +>IdentifierFieldConstructor : IdentifierFieldConstructor + + SO_FAR extends {identifier: any} ? {} : +>identifier : any + + SO_FAR extends {record: any} ? { +>record : any + + identifier: >(t?: TYPE) => BuildPubSubRecordType +>identifier : >(t?: TYPE) => BuildPubSubRecordType +>t : TYPE +>identifier : TYPE + + } : {} + + const buildIdentifierFieldConstructor = (soFar: SO_FAR) => ( +>buildIdentifierFieldConstructor : (soFar: SO_FAR) => { identifier?: undefined; } | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } +>(soFar: SO_FAR) => ( "identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType } ) : (soFar: SO_FAR) => { identifier?: undefined; } | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR +>( "identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType } ) : {} | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } + + "identifier" in soFar || (!("record" in soFar)) ? {} : { +>"identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType } : {} | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } +>"identifier" in soFar || (!("record" in soFar)) : boolean +>"identifier" in soFar : boolean +>"identifier" : "identifier" +>soFar : SO_FAR +>(!("record" in soFar)) : boolean +>!("record" in soFar) : boolean +>("record" in soFar) : boolean +>"record" in soFar : boolean +>"record" : "record" +>soFar : SO_FAR +>{} : {} +>{ identifier: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType } : { identifier: (instance?: TYPE) => BuildPubSubRecordType; } + + identifier: (instance: TYPE = undefined) => +>identifier : (instance?: TYPE) => BuildPubSubRecordType +>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType : (instance?: TYPE) => BuildPubSubRecordType +>instance : TYPE +>undefined : undefined + + buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE} : SO_FAR & { identifier: TYPE; } +>Object.assign({}, soFar, {identifier: instance as TYPE}) : SO_FAR & { identifier: TYPE; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{identifier: instance as TYPE} : { identifier: TYPE; } +>identifier : TYPE +>instance as TYPE : TYPE +>instance : TYPE +>identifier : TYPE +>identifier : TYPE + } + ); + + type RecordFieldConstructor = +>RecordFieldConstructor : RecordFieldConstructor + + SO_FAR extends {record: any} ? {} : { +>record : any + + record: (t?: TYPE) => BuildPubSubRecordType +>record : (t?: TYPE) => BuildPubSubRecordType +>t : TYPE +>record : TYPE + } + + const buildRecordFieldConstructor = (soFar: SO_FAR) => ( +>buildRecordFieldConstructor : (soFar: SO_FAR) => { record?: undefined; } | { record: (instance?: TYPE) => BuildPubSubRecordType; } +>(soFar: SO_FAR) => ( "record" in soFar ? {} : { record: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType } ) : (soFar: SO_FAR) => { record?: undefined; } | { record: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR +>( "record" in soFar ? {} : { record: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType } ) : {} | { record: (instance?: TYPE) => BuildPubSubRecordType; } + + "record" in soFar ? {} : { +>"record" in soFar ? {} : { record: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType } : {} | { record: (instance?: TYPE) => BuildPubSubRecordType; } +>"record" in soFar : boolean +>"record" : "record" +>soFar : SO_FAR +>{} : {} +>{ record: (instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType } : { record: (instance?: TYPE) => BuildPubSubRecordType; } + + record: (instance: TYPE = undefined) => +>record : (instance?: TYPE) => BuildPubSubRecordType +>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType : (instance?: TYPE) => BuildPubSubRecordType +>instance : TYPE +>undefined : undefined + + buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE} : SO_FAR & { record: TYPE; } +>Object.assign({}, soFar, {record: instance as TYPE}) : SO_FAR & { record: TYPE; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{record: instance as TYPE} : { record: TYPE; } +>record : TYPE +>instance as TYPE : TYPE +>instance : TYPE +>record : TYPE +>record : TYPE + } + ); + + type MaxMsToWaitBeforePublishingFieldConstructor = +>MaxMsToWaitBeforePublishingFieldConstructor : MaxMsToWaitBeforePublishingFieldConstructor + + SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : { +>maxMsToWaitBeforePublishing : any + + maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType, +>maxMsToWaitBeforePublishing : (t: number) => BuildPubSubRecordType +>t : number +>maxMsToWaitBeforePublishing : number + + neverDelayPublishing: () => BuildPubSubRecordType, +>neverDelayPublishing : () => BuildPubSubRecordType +>maxMsToWaitBeforePublishing : 0 + } + + const buildMaxMsToWaitBeforePublishingFieldConstructor = (soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor => ( +>buildMaxMsToWaitBeforePublishingFieldConstructor : (soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor +>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor => ( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, } ) as MaxMsToWaitBeforePublishingFieldConstructor : (soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor +>soFar : SO_FAR +>( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, } ) as MaxMsToWaitBeforePublishingFieldConstructor : MaxMsToWaitBeforePublishingFieldConstructor +>( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, } ) : {} | { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType; neverDelayPublishing: () => BuildPubSubRecordType; } + + "maxMsToWaitBeforePublishing" in soFar ? {} : { +>"maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, } : {} | { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType; neverDelayPublishing: () => BuildPubSubRecordType; } +>"maxMsToWaitBeforePublishing" in soFar : boolean +>"maxMsToWaitBeforePublishing" : "maxMsToWaitBeforePublishing" +>soFar : SO_FAR +>{} : {} +>{ maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, } : { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType; neverDelayPublishing: () => BuildPubSubRecordType; } + + maxMsToWaitBeforePublishing: (instance: number = 0) => +>maxMsToWaitBeforePublishing : (instance?: number) => BuildPubSubRecordType +>(instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType : (instance?: number) => BuildPubSubRecordType +>instance : number +>0 : 0 + + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, +>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance}) : SO_FAR & { maxMsToWaitBeforePublishing: number; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{maxMsToWaitBeforePublishing: instance} : { maxMsToWaitBeforePublishing: number; } +>maxMsToWaitBeforePublishing : number +>instance : number +>maxMsToWaitBeforePublishing : number + + neverDelayPublishing: () => +>neverDelayPublishing : () => BuildPubSubRecordType +>() => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType : () => BuildPubSubRecordType + + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, +>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType : BuildPubSubRecordType +>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) : BuildPubSubRecordType +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0}) : SO_FAR & { maxMsToWaitBeforePublishing: number; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>{} : {} +>soFar : SO_FAR +>{maxMsToWaitBeforePublishing: 0} : { maxMsToWaitBeforePublishing: number; } +>maxMsToWaitBeforePublishing : number +>0 : 0 +>maxMsToWaitBeforePublishing : 0 + } + ) as MaxMsToWaitBeforePublishingFieldConstructor; + + type TypeConstructor = +>TypeConstructor : TypeConstructor + + SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? { +>identifier : any +>record : any +>maxMsToWaitBeforePublishing : number +>storedAs : PubSubRecordIsStoredInRedisAsA + + type: SO_FAR, +>type : SO_FAR + + fields: Set, +>fields : Set + + hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR +>hasField : (fieldName: string | number | symbol) => fieldName is keyof SO_FAR +>fieldName : string | number | symbol + + } : {} + + const buildType = (soFar: SO_FAR) => ( +>buildType : (soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } +>(soFar: SO_FAR) => ( "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { type: soFar, fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), hasField: (fieldName: string | number | symbol) => fieldName in soFar } ) : (soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } +>soFar : SO_FAR +>( "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { type: soFar, fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), hasField: (fieldName: string | number | symbol) => fieldName in soFar } ) : {} | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } + + "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { +>"identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { type: soFar, fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), hasField: (fieldName: string | number | symbol) => fieldName in soFar } : {} | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } +>"identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar : boolean +>"identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar : boolean +>"identifier" in soFar && "object" in soFar : boolean +>"identifier" in soFar : boolean +>"identifier" : "identifier" +>soFar : SO_FAR +>"object" in soFar : boolean +>"object" : "object" +>soFar : SO_FAR +>"maxMsToWaitBeforePublishing" in soFar : boolean +>"maxMsToWaitBeforePublishing" : "maxMsToWaitBeforePublishing" +>soFar : SO_FAR +>"PubSubRecordIsStoredInRedisAsA" in soFar : boolean +>"PubSubRecordIsStoredInRedisAsA" : "PubSubRecordIsStoredInRedisAsA" +>soFar : SO_FAR +>{} : {} +>{ type: soFar, fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), hasField: (fieldName: string | number | symbol) => fieldName in soFar } : { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } + + type: soFar, +>type : SO_FAR +>soFar : SO_FAR + + fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), +>fields : () => Set +>() => new Set(Object.keys(soFar) as (keyof SO_FAR)[]) : () => Set +>new Set(Object.keys(soFar) as (keyof SO_FAR)[]) : Set +>Set : SetConstructor +>Object.keys(soFar) as (keyof SO_FAR)[] : (keyof SO_FAR)[] +>Object.keys(soFar) : string[] +>Object.keys : (o: {}) => string[] +>Object : ObjectConstructor +>keys : (o: {}) => string[] +>soFar : SO_FAR + + hasField: (fieldName: string | number | symbol) => fieldName in soFar +>hasField : (fieldName: string | number | symbol) => boolean +>(fieldName: string | number | symbol) => fieldName in soFar : (fieldName: string | number | symbol) => boolean +>fieldName : string | number | symbol +>fieldName in soFar : boolean +>fieldName : string | number | symbol +>soFar : SO_FAR + } + ); + + type BuildPubSubRecordType = +>BuildPubSubRecordType : BuildPubSubRecordType + + NameFieldConstructor & + IdentifierFieldConstructor & + RecordFieldConstructor & + StoredAsConstructor & // infinite loop goes away when you comment out this line + MaxMsToWaitBeforePublishingFieldConstructor & + TypeConstructor + + const buildPubSubRecordType = (soFar: SO_FAR) => Object.assign( +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>(soFar: SO_FAR) => Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) as BuildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>soFar : SO_FAR +>Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) as BuildPubSubRecordType : BuildPubSubRecordType +>Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) : any +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } + + {}, +>{} : {} + + buildNameFieldConstructor(soFar), +>buildNameFieldConstructor(soFar) : { name?: undefined; } | { name: (instance?: TYPE) => BuildPubSubRecordType; } +>buildNameFieldConstructor : (soFar: SO_FAR) => { name?: undefined; } | { name: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR + + buildIdentifierFieldConstructor(soFar), +>buildIdentifierFieldConstructor(soFar) : { identifier?: undefined; } | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } +>buildIdentifierFieldConstructor : (soFar: SO_FAR) => { identifier?: undefined; } | { identifier: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR + + buildRecordFieldConstructor(soFar), +>buildRecordFieldConstructor(soFar) : { record?: undefined; } | { record: (instance?: TYPE) => BuildPubSubRecordType; } +>buildRecordFieldConstructor : (soFar: SO_FAR) => { record?: undefined; } | { record: (instance?: TYPE) => BuildPubSubRecordType; } +>soFar : SO_FAR + + buildStoredAsConstructor(soFar), +>buildStoredAsConstructor(soFar) : { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } +>buildStoredAsConstructor : (soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; storedAsRedisHash: () => BuildPubSubRecordType; } +>soFar : SO_FAR + + buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), +>buildMaxMsToWaitBeforePublishingFieldConstructor(soFar) : MaxMsToWaitBeforePublishingFieldConstructor +>buildMaxMsToWaitBeforePublishingFieldConstructor : (soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor +>soFar : SO_FAR + + buildType(soFar) +>buildType(soFar) : { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } +>buildType : (soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set; hasField: (fieldName: string | number | symbol) => boolean; } +>soFar : SO_FAR + + ) as BuildPubSubRecordType; + const PubSubRecordType = buildPubSubRecordType({}); +>PubSubRecordType : BuildPubSubRecordType<{}> +>buildPubSubRecordType({}) : BuildPubSubRecordType<{}> +>buildPubSubRecordType : (soFar: SO_FAR) => BuildPubSubRecordType +>{} : {} + diff --git a/tests/cases/compiler/conditionalTypeDoesntSpinForever.ts b/tests/cases/compiler/conditionalTypeDoesntSpinForever.ts new file mode 100644 index 0000000000000..9ffbd57ffa17b --- /dev/null +++ b/tests/cases/compiler/conditionalTypeDoesntSpinForever.ts @@ -0,0 +1,119 @@ +// @target: es6 +// A *self-contained* demonstration of the problem follows... +// Test this by running `tsc --target es6` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. + +export enum PubSubRecordIsStoredInRedisAsA { + redisHash = "redisHash", + jsonEncodedRedisString = "jsonEncodedRedisString" + } + + export interface PubSubRecord> { + name: NAME; + record: RECORD; + identifier: IDENTIFIER; + storedAs: PubSubRecordIsStoredInRedisAsA; + maxMsToWaitBeforePublishing: number; + } + + type NameFieldConstructor = + SO_FAR extends {name: any} ? {} : { + name: (t?: TYPE) => BuildPubSubRecordType + } + + const buildNameFieldConstructor = (soFar: SO_FAR) => ( + "name" in soFar ? {} : { + name: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType + } + ); + + type StoredAsConstructor = + SO_FAR extends {storedAs: any} ? {} : { + storedAsJsonEncodedRedisString: () => BuildPubSubRecordType; + storedRedisHash: () => BuildPubSubRecordType; + } + + const buildStoredAsConstructor = (soFar: SO_FAR) => ( + "storedAs" in soFar ? {} : { + storedAsJsonEncodedRedisString: () => + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as + BuildPubSubRecordType, + storedAsRedisHash: () => + buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as + BuildPubSubRecordType, + } + ); + + type IdentifierFieldConstructor = + SO_FAR extends {identifier: any} ? {} : + SO_FAR extends {record: any} ? { + identifier: >(t?: TYPE) => BuildPubSubRecordType + } : {} + + const buildIdentifierFieldConstructor = (soFar: SO_FAR) => ( + "identifier" in soFar || (!("record" in soFar)) ? {} : { + identifier: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType + } + ); + + type RecordFieldConstructor = + SO_FAR extends {record: any} ? {} : { + record: (t?: TYPE) => BuildPubSubRecordType + } + + const buildRecordFieldConstructor = (soFar: SO_FAR) => ( + "record" in soFar ? {} : { + record: (instance: TYPE = undefined) => + buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType + } + ); + + type MaxMsToWaitBeforePublishingFieldConstructor = + SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : { + maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType, + neverDelayPublishing: () => BuildPubSubRecordType, + } + + const buildMaxMsToWaitBeforePublishingFieldConstructor = (soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor => ( + "maxMsToWaitBeforePublishing" in soFar ? {} : { + maxMsToWaitBeforePublishing: (instance: number = 0) => + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType, + neverDelayPublishing: () => + buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType, + } + ) as MaxMsToWaitBeforePublishingFieldConstructor; + + type TypeConstructor = + SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? { + type: SO_FAR, + fields: Set, + hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR + } : {} + + const buildType = (soFar: SO_FAR) => ( + "identifier" in soFar && "object" in soFar && "maxMsToWaitBeforePublishing" in soFar && "PubSubRecordIsStoredInRedisAsA" in soFar ? {} : { + type: soFar, + fields: () => new Set(Object.keys(soFar) as (keyof SO_FAR)[]), + hasField: (fieldName: string | number | symbol) => fieldName in soFar + } + ); + + type BuildPubSubRecordType = + NameFieldConstructor & + IdentifierFieldConstructor & + RecordFieldConstructor & + StoredAsConstructor & // infinite loop goes away when you comment out this line + MaxMsToWaitBeforePublishingFieldConstructor & + TypeConstructor + + const buildPubSubRecordType = (soFar: SO_FAR) => Object.assign( + {}, + buildNameFieldConstructor(soFar), + buildIdentifierFieldConstructor(soFar), + buildRecordFieldConstructor(soFar), + buildStoredAsConstructor(soFar), + buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), + buildType(soFar) + ) as BuildPubSubRecordType; + const PubSubRecordType = buildPubSubRecordType({}); \ No newline at end of file From 23912e0f3cc00e5b69f4726d80ad77fcfe2c444f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 22 Oct 2018 16:26:33 -0700 Subject: [PATCH 2/4] Just do variance probing for all type aliases --- src/compiler/checker.ts | 20 +++++++++++-------- .../reference/conditionalTypes1.errors.txt | 8 -------- .../strictFunctionTypesErrors.errors.txt | 4 ---- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a4d834fbf43fd..a1ef7411cbe83 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11927,9 +11927,21 @@ namespace ts { } return Ternary.False; } + let result: Ternary; let originalErrorInfo: DiagnosticMessageChain | undefined; const saveErrorInfo = errorInfo; + + if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && + !(getAliasArgumentsContainsMarker(source) || getAliasArgumentsContainsMarker(target))) { + const variances = getAliasVariances(source.aliasSymbol); + if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) { + return result; + } + originalErrorInfo = errorInfo; + errorInfo = saveErrorInfo; + } + if (target.flags & TypeFlags.TypeParameter) { // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P]. if (getObjectFlags(source) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(source) === getIndexType(target)) { @@ -12032,14 +12044,6 @@ namespace ts { } else if (source.flags & TypeFlags.Conditional) { if (target.flags & TypeFlags.Conditional) { - if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && - !(getAliasArgumentsContainsMarker(source) || getAliasArgumentsContainsMarker(target))) { - const variances = getAliasVariances(source.aliasSymbol); - if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) { - errorInfo = saveErrorInfo; - return result; - } - } // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, // and Y1 is related to Y2. diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt index 7ba3a2aa9344a..4018e0866d666 100644 --- a/tests/baselines/reference/conditionalTypes1.errors.txt +++ b/tests/baselines/reference/conditionalTypes1.errors.txt @@ -17,12 +17,8 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(103,5): error TS2 tests/cases/conformance/types/conditional/conditionalTypes1.ts(104,5): error TS2322: Type 'Pick' is not assignable to type 'T'. tests/cases/conformance/types/conditional/conditionalTypes1.ts(106,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. - Type 'keyof T' is not assignable to type 'never'. - Type 'string | number | symbol' is not assignable to type 'never'. - Type 'string' is not assignable to type 'never'. tests/cases/conformance/types/conditional/conditionalTypes1.ts(108,5): error TS2322: Type 'Pick' is not assignable to type 'Pick'. Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. - Type 'keyof T' is not assignable to type 'never'. tests/cases/conformance/types/conditional/conditionalTypes1.ts(114,5): error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. Type 'string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. @@ -187,15 +183,11 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS ~ !!! error TS2322: Type 'Pick' is not assignable to type 'Pick'. !!! error TS2322: Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'. -!!! error TS2322: Type 'keyof T' is not assignable to type 'never'. -!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'never'. -!!! error TS2322: Type 'string' is not assignable to type 'never'. z = x; z = y; // Error ~ !!! error TS2322: Type 'Pick' is not assignable to type 'Pick'. !!! error TS2322: Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'. -!!! error TS2322: Type 'keyof T' is not assignable to type 'never'. } function f8(x: keyof T, y: FunctionPropertyNames, z: NonFunctionPropertyNames) { diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index d8e36e43060d7..965bbee0ea1c7 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -58,8 +58,6 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(67,1): error TS2322: Type 'Fun Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(74,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Type 'Func' is not assignable to type 'Func'. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(75,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Types of parameters 'x' and 'x' are incompatible. Type 'Object' is not assignable to type 'string'. @@ -261,8 +259,6 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(c ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. !!! error TS2322: Type 'Func' is not assignable to type 'Func'. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. i1 = i3; // Error ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. From 966d0b86a6b472851a0718463eb7bfdddf9d71af Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 22 Oct 2018 16:42:58 -0700 Subject: [PATCH 3/4] Small limiter for predictability --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a1ef7411cbe83..f592dd5cbf644 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11932,7 +11932,11 @@ namespace ts { let originalErrorInfo: DiagnosticMessageChain | undefined; const saveErrorInfo = errorInfo; - if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && + // We limit alias variance probing to only object and conditional types since their alias behavior + // is more predictable than other, interned types, which may or may not have an alias depending on + // the order in which things were checked. + if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && + source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && !(getAliasArgumentsContainsMarker(source) || getAliasArgumentsContainsMarker(target))) { const variances = getAliasVariances(source.aliasSymbol); if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) { From d5385e9bcae88e7edbfcc3f235759457e09e42c1 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 26 Oct 2018 16:05:10 -0700 Subject: [PATCH 4/4] Inline property set, remove unused functions --- src/compiler/checker.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 916516ab9741e..1d685e15a98fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11942,7 +11942,7 @@ namespace ts { // the order in which things were checked. if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && - !(getAliasArgumentsContainsMarker(source) || getAliasArgumentsContainsMarker(target))) { + !(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) { const variances = getAliasVariances(source.aliasSymbol); if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) { return result; @@ -12618,23 +12618,13 @@ namespace ts { return result; } - function isMarkerType(type: Type) { - return type === markerSuperType || type === markerSubType || type === markerOtherType; - } - - function getAliasArgumentsContainsMarker(type: Type) { - if (!type.aliasSymbol || !type.aliasTypeArguments) { - return false; - } - if (type.aliasTypeArgumentsContainsMarker !== undefined) { - return type.aliasTypeArgumentsContainsMarker; - } - return type.aliasTypeArgumentsContainsMarker = some(type.aliasTypeArguments, isMarkerType); - } - function getAliasVariances(symbol: Symbol) { const links = getSymbolLinks(symbol); - return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)))); + return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => { + const type = getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker))); + type.aliasTypeArgumentsContainsMarker = true; + return type; + }); } // Return an array containing the variance of each type parameter. The variance is effectively