Measure variance of aliased conditional types using variance markers (#27804)

* Measure variance of aliased conditional types using variance markers

* Just do variance probing for all type aliases

* Small limiter for predictability

* Inline property set, remove unused functions
This commit is contained in:
Wesley Wigham 2018-10-26 16:26:20 -07:00 committed by GitHub
parent ccc16136b2
commit e2100cd2cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1336 additions and 75 deletions

View File

@ -7636,35 +7636,35 @@ namespace ts {
* @param typeParameters The requested type parameters.
* @param minTypeArgumentCount The minimum number of required type arguments.
*/
function fillMissingTypeArguments(typeArguments: Type[], typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
function fillMissingTypeArguments(typeArguments: ReadonlyArray<Type>, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
function fillMissingTypeArguments(typeArguments: ReadonlyArray<Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
function fillMissingTypeArguments(typeArguments: ReadonlyArray<Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
const numTypeParameters = length(typeParameters);
if (numTypeParameters) {
const numTypeArguments = length(typeArguments);
if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
if (!typeArguments) {
typeArguments = [];
}
// 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);
}
typeArguments.length = typeParameters!.length;
}
if (!numTypeParameters) {
return [];
}
return typeArguments;
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++) {
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;
}
result[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny);
}
result.length = typeParameters!.length;
return result;
}
return typeArguments && typeArguments.slice();
}
function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature {
@ -8262,7 +8262,7 @@ namespace ts {
return checkNoTypeArguments(node, symbol) ? type : errorType;
}
function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[] | undefined): Type {
function getTypeAliasInstantiation(symbol: Symbol, typeArguments: ReadonlyArray<Type> | undefined): Type {
const type = getDeclaredTypeOfSymbol(symbol);
const links = getSymbolLinks(symbol);
const typeParameters = links.typeParameters!;
@ -11783,9 +11783,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<Type> = emptyArray, targets: ReadonlyArray<Type> = emptyArray, variances: ReadonlyArray<Variance> = emptyArray, reportErrors: boolean): Ternary {
if (sources.length !== targets.length && relation === identityRelation) {
return Ternary.False;
}
@ -11938,9 +11936,25 @@ namespace ts {
}
return Ternary.False;
}
let result: Ternary;
let originalErrorInfo: DiagnosticMessageChain | undefined;
const saveErrorInfo = errorInfo;
// 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 &&
!(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) {
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(<MappedType>source) === getIndexType(target)) {
@ -12101,7 +12115,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((<TypeReference>source).target);
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, variances, reportErrors)) {
if (result = typeArgumentsRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, variances, reportErrors)) {
return result;
}
// The type arguments did not relate appropriately, but it may be because we have no variance
@ -12608,48 +12622,58 @@ namespace ts {
return result;
}
function getAliasVariances(symbol: Symbol) {
const links = getSymbolLinks(symbol);
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
// 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<TCache extends { variances?: Variance[] }>(typeParameters: ReadonlyArray<TypeParameter> = 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.

View File

@ -3647,6 +3647,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<string>; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings
variances?: Variance[]; // Alias symbol type argument variance cache
}
/* @internal */
@ -3899,6 +3900,7 @@ namespace ts {
pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any)
aliasSymbol?: Symbol; // Alias associated with type
aliasTypeArguments?: ReadonlyArray<Type>; // 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 */

View File

@ -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 extends string, RECORD, IDENTIFIER extends Partial<RECORD>> {
name: NAME;
record: RECORD;
identifier: IDENTIFIER;
storedAs: PubSubRecordIsStoredInRedisAsA;
maxMsToWaitBeforePublishing: number;
}
type NameFieldConstructor<SO_FAR> =
SO_FAR extends {name: any} ? {} : {
name: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {name: TYPE}>
}
const buildNameFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"name" in soFar ? {} : {
name: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}>
}
);
type StoredAsConstructor<SO_FAR> =
SO_FAR extends {storedAs: any} ? {} : {
storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>;
storedRedisHash: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>;
}
const buildStoredAsConstructor = <SO_FAR>(soFar: SO_FAR) => (
"storedAs" in soFar ? {} : {
storedAsJsonEncodedRedisString: () =>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as
BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>,
storedAsRedisHash: () =>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as
BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>,
}
);
type IdentifierFieldConstructor<SO_FAR> =
SO_FAR extends {identifier: any} ? {} :
SO_FAR extends {record: any} ? {
identifier: <TYPE extends Partial<SO_FAR["record"]>>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
} : {}
const buildIdentifierFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"identifier" in soFar || (!("record" in soFar)) ? {} : {
identifier: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
}
);
type RecordFieldConstructor<SO_FAR> =
SO_FAR extends {record: any} ? {} : {
record: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {record: TYPE}>
}
const buildRecordFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"record" in soFar ? {} : {
record: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}>
}
);
type MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> =
SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : {
maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
}
const buildMaxMsToWaitBeforePublishingFieldConstructor = <SO_FAR>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> => (
"maxMsToWaitBeforePublishing" in soFar ? {} : {
maxMsToWaitBeforePublishing: (instance: number = 0) =>
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
neverDelayPublishing: () =>
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
}
) as MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>;
type TypeConstructor<SO_FAR> =
SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? {
type: SO_FAR,
fields: Set<keyof SO_FAR>,
hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR
} : {}
const buildType = <SO_FAR>(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<SO_FAR> =
NameFieldConstructor<SO_FAR> &
IdentifierFieldConstructor<SO_FAR> &
RecordFieldConstructor<SO_FAR> &
StoredAsConstructor<SO_FAR> & // infinite loop goes away when you comment out this line
MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> &
TypeConstructor<SO_FAR>
const buildPubSubRecordType = <SO_FAR>(soFar: SO_FAR) => Object.assign(
{},
buildNameFieldConstructor(soFar),
buildIdentifierFieldConstructor(soFar),
buildRecordFieldConstructor(soFar),
buildStoredAsConstructor(soFar),
buildMaxMsToWaitBeforePublishingFieldConstructor(soFar),
buildType(soFar)
) as BuildPubSubRecordType<SO_FAR>;
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({});

View File

@ -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<NAME extends string, RECORD, IDENTIFIER extends Partial<RECORD>> {
>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<SO_FAR> =
>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: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {name: TYPE}>
>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 = <SO_FAR>(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: <TYPE>(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<SO_FAR & {name: TYPE}>
>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<SO_FAR> =
>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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>;
>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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>;
>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 = <SO_FAR>(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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>,
>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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>,
>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<SO_FAR> =
>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: <TYPE extends Partial<SO_FAR["record"]>>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
>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 = <SO_FAR>(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: <TYPE>(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<SO_FAR & {identifier: TYPE}>
>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<SO_FAR> =
>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: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {record: TYPE}>
>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 = <SO_FAR>(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: <TYPE>(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<SO_FAR & {record: TYPE}>
>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<SO_FAR> =
>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<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
>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<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
>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 = <SO_FAR>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> => (
>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<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
>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<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
>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<SO_FAR>;
>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 76, 60))
type TypeConstructor<SO_FAR> =
>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<keyof SO_FAR>,
>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 = <SO_FAR>(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<SO_FAR> =
>BuildPubSubRecordType : Symbol(BuildPubSubRecordType, Decl(conditionalTypeDoesntSpinForever.ts, 98, 4))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
NameFieldConstructor<SO_FAR> &
>NameFieldConstructor : Symbol(NameFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 14, 3))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
IdentifierFieldConstructor<SO_FAR> &
>IdentifierFieldConstructor : Symbol(IdentifierFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 43, 4))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
RecordFieldConstructor<SO_FAR> &
>RecordFieldConstructor : Symbol(RecordFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 56, 4))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
StoredAsConstructor<SO_FAR> & // 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<SO_FAR> &
>MaxMsToWaitBeforePublishingFieldConstructor : Symbol(MaxMsToWaitBeforePublishingFieldConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 68, 4))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
TypeConstructor<SO_FAR>
>TypeConstructor : Symbol(TypeConstructor, Decl(conditionalTypeDoesntSpinForever.ts, 83, 59))
>SO_FAR : Symbol(SO_FAR, Decl(conditionalTypeDoesntSpinForever.ts, 100, 29))
const buildPubSubRecordType = <SO_FAR>(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<SO_FAR>;
>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))

View File

@ -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 extends string, RECORD, IDENTIFIER extends Partial<RECORD>> {
name: NAME;
>name : NAME
record: RECORD;
>record : RECORD
identifier: IDENTIFIER;
>identifier : IDENTIFIER
storedAs: PubSubRecordIsStoredInRedisAsA;
>storedAs : PubSubRecordIsStoredInRedisAsA
maxMsToWaitBeforePublishing: number;
>maxMsToWaitBeforePublishing : number
}
type NameFieldConstructor<SO_FAR> =
>NameFieldConstructor : NameFieldConstructor<SO_FAR>
SO_FAR extends {name: any} ? {} : {
>name : any
name: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {name: TYPE}>
>name : <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>
>t : TYPE
>name : TYPE
}
const buildNameFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
>buildNameFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
><SO_FAR>(soFar: SO_FAR) => ( "name" in soFar ? {} : { name: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> } ) : <SO_FAR>(soFar: SO_FAR) => { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>soFar : SO_FAR
>( "name" in soFar ? {} : { name: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> } ) : {} | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
"name" in soFar ? {} : {
>"name" in soFar ? {} : { name: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> } : {} | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>"name" in soFar : boolean
>"name" : "name"
>soFar : SO_FAR
>{} : {}
>{ name: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> } : { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
name: <TYPE>(instance: TYPE = undefined) =>
>name : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>
><TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>
>instance : TYPE
>undefined : undefined
buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}>
>buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}> : BuildPubSubRecordType<SO_FAR & { name: TYPE; }>
>buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) : BuildPubSubRecordType<SO_FAR & { name: TYPE; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>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 : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR> =
>StoredAsConstructor : StoredAsConstructor<SO_FAR>
SO_FAR extends {storedAs: any} ? {} : {
>storedAs : any
storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>;
>storedAsJsonEncodedRedisString : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>
>storedAs : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString
>PubSubRecordIsStoredInRedisAsA : any
storedRedisHash: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>;
>storedRedisHash : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>
>storedAs : PubSubRecordIsStoredInRedisAsA.redisHash
>PubSubRecordIsStoredInRedisAsA : any
}
const buildStoredAsConstructor = <SO_FAR>(soFar: SO_FAR) => (
>buildStoredAsConstructor : <SO_FAR>(soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
><SO_FAR>(soFar: SO_FAR) => ( "storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>, } ) : <SO_FAR>(soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>soFar : SO_FAR
>( "storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>, } ) : {} | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
"storedAs" in soFar ? {} : {
>"storedAs" in soFar ? {} : { storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>, } : {} | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>"storedAs" in soFar : boolean
>"storedAs" : "storedAs"
>soFar : SO_FAR
>{} : {}
>{ storedAsJsonEncodedRedisString: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>, storedAsRedisHash: () => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>, } : { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
storedAsJsonEncodedRedisString: () =>
>storedAsJsonEncodedRedisString : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>
>() => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}> : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as
>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}> : BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>
>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) : BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}) : SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; }
>Object.assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>,
>storedAs : PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString
>PubSubRecordIsStoredInRedisAsA : any
storedAsRedisHash: () =>
>storedAsRedisHash : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>
>() => buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}> : () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as
>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}> : BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>
>buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) : BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}) : SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA; }
>Object.assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>,
>storedAs : PubSubRecordIsStoredInRedisAsA.redisHash
>PubSubRecordIsStoredInRedisAsA : any
}
);
type IdentifierFieldConstructor<SO_FAR> =
>IdentifierFieldConstructor : IdentifierFieldConstructor<SO_FAR>
SO_FAR extends {identifier: any} ? {} :
>identifier : any
SO_FAR extends {record: any} ? {
>record : any
identifier: <TYPE extends Partial<SO_FAR["record"]>>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
>identifier : <TYPE extends Partial<SO_FAR["record"]>>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>
>t : TYPE
>identifier : TYPE
} : {}
const buildIdentifierFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
>buildIdentifierFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
><SO_FAR>(soFar: SO_FAR) => ( "identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> } ) : <SO_FAR>(soFar: SO_FAR) => { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>soFar : SO_FAR
>( "identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> } ) : {} | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
"identifier" in soFar || (!("record" in soFar)) ? {} : {
>"identifier" in soFar || (!("record" in soFar)) ? {} : { identifier: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> } : {} | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>"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: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> } : { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
identifier: <TYPE>(instance: TYPE = undefined) =>
>identifier : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>
><TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>
>instance : TYPE
>undefined : undefined
buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
>buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}> : BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>
>buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) : BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>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 : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR> =
>RecordFieldConstructor : RecordFieldConstructor<SO_FAR>
SO_FAR extends {record: any} ? {} : {
>record : any
record: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {record: TYPE}>
>record : <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>
>t : TYPE
>record : TYPE
}
const buildRecordFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
>buildRecordFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
><SO_FAR>(soFar: SO_FAR) => ( "record" in soFar ? {} : { record: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> } ) : <SO_FAR>(soFar: SO_FAR) => { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>soFar : SO_FAR
>( "record" in soFar ? {} : { record: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> } ) : {} | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
"record" in soFar ? {} : {
>"record" in soFar ? {} : { record: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> } : {} | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>"record" in soFar : boolean
>"record" : "record"
>soFar : SO_FAR
>{} : {}
>{ record: <TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> } : { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
record: <TYPE>(instance: TYPE = undefined) =>
>record : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>
><TYPE>(instance: TYPE = undefined) => buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> : <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>
>instance : TYPE
>undefined : undefined
buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}>
>buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}> : BuildPubSubRecordType<SO_FAR & { record: TYPE; }>
>buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) : BuildPubSubRecordType<SO_FAR & { record: TYPE; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>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 : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR> =
>MaxMsToWaitBeforePublishingFieldConstructor : MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : {
>maxMsToWaitBeforePublishing : any
maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
>maxMsToWaitBeforePublishing : (t: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>t : number
>maxMsToWaitBeforePublishing : number
neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
>neverDelayPublishing : () => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>
>maxMsToWaitBeforePublishing : 0
}
const buildMaxMsToWaitBeforePublishingFieldConstructor = <SO_FAR>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> => (
>buildMaxMsToWaitBeforePublishingFieldConstructor : <SO_FAR>(soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
><SO_FAR>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> => ( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>, } ) as MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> : <SO_FAR>(soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
>soFar : SO_FAR
>( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>, } ) as MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> : MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
>( "maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>, } ) : {} | { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>; neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>; }
"maxMsToWaitBeforePublishing" in soFar ? {} : {
>"maxMsToWaitBeforePublishing" in soFar ? {} : { maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>, } : {} | { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>; neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>; }
>"maxMsToWaitBeforePublishing" in soFar : boolean
>"maxMsToWaitBeforePublishing" : "maxMsToWaitBeforePublishing"
>soFar : SO_FAR
>{} : {}
>{ maxMsToWaitBeforePublishing: (instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>, neverDelayPublishing: () => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>, } : { maxMsToWaitBeforePublishing: (instance?: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>; neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>; }
maxMsToWaitBeforePublishing: (instance: number = 0) =>
>maxMsToWaitBeforePublishing : (instance?: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>(instance: number = 0) => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}> : (instance?: number) => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>instance : number
>0 : 0
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}> : BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) : BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance}) : SO_FAR & { maxMsToWaitBeforePublishing: number; }
>Object.assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>
>() => buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}> : () => BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}> : BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: 0; }>
>buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) : BuildPubSubRecordType<SO_FAR & { maxMsToWaitBeforePublishing: number; }>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0}) : SO_FAR & { maxMsToWaitBeforePublishing: number; }
>Object.assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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<SO_FAR>;
type TypeConstructor<SO_FAR> =
>TypeConstructor : TypeConstructor<SO_FAR>
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<keyof SO_FAR>,
>fields : Set<keyof SO_FAR>
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 = <SO_FAR>(soFar: SO_FAR) => (
>buildType : <SO_FAR>(soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
><SO_FAR>(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 } ) : <SO_FAR>(soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; 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<keyof SO_FAR>; 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<keyof SO_FAR>; 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<keyof SO_FAR>; 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<keyof SO_FAR>
>() => new Set(Object.keys(soFar) as (keyof SO_FAR)[]) : () => Set<keyof SO_FAR>
>new Set(Object.keys(soFar) as (keyof SO_FAR)[]) : Set<keyof SO_FAR>
>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<SO_FAR> =
>BuildPubSubRecordType : BuildPubSubRecordType<SO_FAR>
NameFieldConstructor<SO_FAR> &
IdentifierFieldConstructor<SO_FAR> &
RecordFieldConstructor<SO_FAR> &
StoredAsConstructor<SO_FAR> & // infinite loop goes away when you comment out this line
MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> &
TypeConstructor<SO_FAR>
const buildPubSubRecordType = <SO_FAR>(soFar: SO_FAR) => Object.assign(
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
><SO_FAR>(soFar: SO_FAR) => Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) as BuildPubSubRecordType<SO_FAR> : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>soFar : SO_FAR
>Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) as BuildPubSubRecordType<SO_FAR> : BuildPubSubRecordType<SO_FAR>
>Object.assign( {}, buildNameFieldConstructor(soFar), buildIdentifierFieldConstructor(soFar), buildRecordFieldConstructor(soFar), buildStoredAsConstructor(soFar), buildMaxMsToWaitBeforePublishingFieldConstructor(soFar), buildType(soFar) ) : any
>Object.assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
{},
>{} : {}
buildNameFieldConstructor(soFar),
>buildNameFieldConstructor(soFar) : { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>buildNameFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>soFar : SO_FAR
buildIdentifierFieldConstructor(soFar),
>buildIdentifierFieldConstructor(soFar) : { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>buildIdentifierFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>soFar : SO_FAR
buildRecordFieldConstructor(soFar),
>buildRecordFieldConstructor(soFar) : { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>buildRecordFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>soFar : SO_FAR
buildStoredAsConstructor(soFar),
>buildStoredAsConstructor(soFar) : { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>buildStoredAsConstructor : <SO_FAR>(soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>soFar : SO_FAR
buildMaxMsToWaitBeforePublishingFieldConstructor(soFar),
>buildMaxMsToWaitBeforePublishingFieldConstructor(soFar) : MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
>buildMaxMsToWaitBeforePublishingFieldConstructor : <SO_FAR>(soFar: SO_FAR) => MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>
>soFar : SO_FAR
buildType(soFar)
>buildType(soFar) : { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
>buildType : <SO_FAR>(soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
>soFar : SO_FAR
) as BuildPubSubRecordType<SO_FAR>;
const PubSubRecordType = buildPubSubRecordType({});
>PubSubRecordType : BuildPubSubRecordType<{}>
>buildPubSubRecordType({}) : BuildPubSubRecordType<{}>
>buildPubSubRecordType : <SO_FAR>(soFar: SO_FAR) => BuildPubSubRecordType<SO_FAR>
>{} : {}

View File

@ -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<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'T'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(106,5): error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>'.
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<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>'.
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<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>'.
!!! 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<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>'.
!!! 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<T>(x: keyof T, y: FunctionPropertyNames<T>, z: NonFunctionPropertyNames<T>) {

View File

@ -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<Object, Func<string, void>>' is not assignable to type 'Func<Object, Func<Object, void>>'.
Type 'Func<string, void>' is not assignable to type 'Func<Object, void>'.
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<string, Func<Object, void>>' is not assignable to type 'Func<Object, Func<Object, void>>'.
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<Object, Func<string, void>>' is not assignable to type 'Func<Object, Func<Object, void>>'.
!!! error TS2322: Type 'Func<string, void>' is not assignable to type 'Func<Object, void>'.
!!! 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<string, Func<Object, void>>' is not assignable to type 'Func<Object, Func<Object, void>>'.

View File

@ -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 extends string, RECORD, IDENTIFIER extends Partial<RECORD>> {
name: NAME;
record: RECORD;
identifier: IDENTIFIER;
storedAs: PubSubRecordIsStoredInRedisAsA;
maxMsToWaitBeforePublishing: number;
}
type NameFieldConstructor<SO_FAR> =
SO_FAR extends {name: any} ? {} : {
name: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {name: TYPE}>
}
const buildNameFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"name" in soFar ? {} : {
name: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {name: instance as TYPE}) as SO_FAR & {name: TYPE}) as BuildPubSubRecordType<SO_FAR & {name: TYPE}>
}
);
type StoredAsConstructor<SO_FAR> =
SO_FAR extends {storedAs: any} ? {} : {
storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>;
storedRedisHash: () => BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>;
}
const buildStoredAsConstructor = <SO_FAR>(soFar: SO_FAR) => (
"storedAs" in soFar ? {} : {
storedAsJsonEncodedRedisString: () =>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString})) as
BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString}>,
storedAsRedisHash: () =>
buildPubSubRecordType(Object.assign({}, soFar, {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash})) as
BuildPubSubRecordType<SO_FAR & {storedAs: PubSubRecordIsStoredInRedisAsA.redisHash}>,
}
);
type IdentifierFieldConstructor<SO_FAR> =
SO_FAR extends {identifier: any} ? {} :
SO_FAR extends {record: any} ? {
identifier: <TYPE extends Partial<SO_FAR["record"]>>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
} : {}
const buildIdentifierFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"identifier" in soFar || (!("record" in soFar)) ? {} : {
identifier: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {identifier: instance as TYPE}) as SO_FAR & {identifier: TYPE}) as BuildPubSubRecordType<SO_FAR & {identifier: TYPE}>
}
);
type RecordFieldConstructor<SO_FAR> =
SO_FAR extends {record: any} ? {} : {
record: <TYPE>(t?: TYPE) => BuildPubSubRecordType<SO_FAR & {record: TYPE}>
}
const buildRecordFieldConstructor = <SO_FAR>(soFar: SO_FAR) => (
"record" in soFar ? {} : {
record: <TYPE>(instance: TYPE = undefined) =>
buildPubSubRecordType(Object.assign({}, soFar, {record: instance as TYPE}) as SO_FAR & {record: TYPE}) as BuildPubSubRecordType<SO_FAR & {record: TYPE}>
}
);
type MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> =
SO_FAR extends {maxMsToWaitBeforePublishing: any} ? {} : {
maxMsToWaitBeforePublishing: (t: number) => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
neverDelayPublishing: () => BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
}
const buildMaxMsToWaitBeforePublishingFieldConstructor = <SO_FAR>(soFar: SO_FAR): MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> => (
"maxMsToWaitBeforePublishing" in soFar ? {} : {
maxMsToWaitBeforePublishing: (instance: number = 0) =>
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: instance})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: number}>,
neverDelayPublishing: () =>
buildPubSubRecordType(Object.assign({}, soFar, {maxMsToWaitBeforePublishing: 0})) as BuildPubSubRecordType<SO_FAR & {maxMsToWaitBeforePublishing: 0}>,
}
) as MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR>;
type TypeConstructor<SO_FAR> =
SO_FAR extends {identifier: any, record: any, maxMsToWaitBeforePublishing: number, storedAs: PubSubRecordIsStoredInRedisAsA} ? {
type: SO_FAR,
fields: Set<keyof SO_FAR>,
hasField: (fieldName: string | number | symbol) => fieldName is keyof SO_FAR
} : {}
const buildType = <SO_FAR>(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<SO_FAR> =
NameFieldConstructor<SO_FAR> &
IdentifierFieldConstructor<SO_FAR> &
RecordFieldConstructor<SO_FAR> &
StoredAsConstructor<SO_FAR> & // infinite loop goes away when you comment out this line
MaxMsToWaitBeforePublishingFieldConstructor<SO_FAR> &
TypeConstructor<SO_FAR>
const buildPubSubRecordType = <SO_FAR>(soFar: SO_FAR) => Object.assign(
{},
buildNameFieldConstructor(soFar),
buildIdentifierFieldConstructor(soFar),
buildRecordFieldConstructor(soFar),
buildStoredAsConstructor(soFar),
buildMaxMsToWaitBeforePublishingFieldConstructor(soFar),
buildType(soFar)
) as BuildPubSubRecordType<SO_FAR>;
const PubSubRecordType = buildPubSubRecordType({});