From cbbbda456975c5e5e43785b8e9efdcbf8140a456 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 25 Mar 2019 19:17:09 -0700 Subject: [PATCH 1/5] Unify substitution type `any` handling into costruction and instantiation --- src/compiler/checker.ts | 82 ++++++++-------- src/compiler/types.ts | 6 +- .../reference/api/tsserverlibrary.d.ts | 4 +- tests/baselines/reference/api/typescript.d.ts | 4 +- ...nalNoInfiniteInstantiationDepth.errors.txt | 97 +++++++++++++++++++ ...ditionalNoInfiniteInstantiationDepth.types | 2 +- ...plifyingConditionalTypesNoCrash.errors.txt | 78 +++++++++++++++ ...lySimplifyingConditionalTypesNoCrash.types | 2 +- .../baselines/reference/conditionalTypes1.js | 2 - .../reference/conditionalTypes1.types | 14 +-- .../reference/conditionalTypes2.errors.txt | 9 +- .../reference/conditionalTypes2.types | 6 +- .../reference/infiniteConstraints.errors.txt | 11 ++- ...sCompareCorrectlyInRestrictiveInstances.js | 10 ++ ...areCorrectlyInRestrictiveInstances.symbols | 36 +++++++ ...mpareCorrectlyInRestrictiveInstances.types | 20 ++++ ...sCompareCorrectlyInRestrictiveInstances.ts | 6 ++ 17 files changed, 321 insertions(+), 68 deletions(-) create mode 100644 tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt create mode 100644 tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt create mode 100644 tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.js create mode 100644 tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.symbols create mode 100644 tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.types create mode 100644 tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aaaacd7100762..2cf6c59a3bc3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3492,8 +3492,8 @@ namespace ts { context.inferTypeParameters = (type).root.inferTypeParameters; const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context); context.inferTypeParameters = saveInferTypeParameters; - const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(type), context); - const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context); + const trueTypeNode = typeToTypeNodeHelper((type).resolvedTrueType, context); + const falseTypeNode = typeToTypeNodeHelper((type).resolvedFalseType, context); context.approximateLength += 15; return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } @@ -7477,6 +7477,10 @@ namespace ts { } function getConstraintOfIndexedAccess(type: IndexedAccessType) { + return hasNonCircularBaseConstraint(type) ? getConstraintFromIndexedAccess(type) : undefined; + } + + function getConstraintFromIndexedAccess(type: IndexedAccessType) { const objectType = getConstraintOfType(type.objectType) || type.objectType; if (objectType !== type.objectType) { const constraint = getIndexedAccessType(objectType, type.indexType, /*accessNode*/ undefined, errorType); @@ -7488,24 +7492,14 @@ namespace ts { return baseConstraint && baseConstraint !== type ? baseConstraint : undefined; } - function getDefaultConstraintOfTrueBranchOfConditionalType(root: ConditionalRoot, combinedMapper: TypeMapper | undefined, mapper: TypeMapper | undefined) { - const rootTrueType = root.trueType; - const rootTrueConstraint = !(rootTrueType.flags & TypeFlags.Substitution) - ? rootTrueType - : instantiateType(((rootTrueType).substitute), combinedMapper || mapper).flags & TypeFlags.AnyOrUnknown - ? (rootTrueType).typeVariable - : getIntersectionType([(rootTrueType).substitute, (rootTrueType).typeVariable]); - return instantiateType(rootTrueConstraint, combinedMapper || mapper); - } - function getDefaultConstraintOfConditionalType(type: ConditionalType) { if (!type.resolvedDefaultConstraint) { // An `any` branch of a conditional type would normally be viral - specifically, without special handling here, // a conditional type with a single branch of type `any` would be assignable to anything, since it's constraint would simplify to // just `any`. This result is _usually_ unwanted - so instead here we elide an `any` branch from the constraint type, // in effect treating `any` like `never` rather than `unknown` in this location. - const trueConstraint = getDefaultConstraintOfTrueBranchOfConditionalType(type.root, type.combinedMapper, type.mapper); - const falseConstraint = getFalseTypeFromConditionalType(type); + const trueConstraint = getInferredTrueTypeFromConditionalType(type); + const falseConstraint = type.resolvedFalseType; type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]); } return type.resolvedDefaultConstraint; @@ -7537,10 +7531,14 @@ namespace ts { return undefined; } - function getConstraintOfConditionalType(type: ConditionalType) { + function getConstraintFromConditionalType(type: ConditionalType) { return getConstraintOfDistributiveConditionalType(type) || getDefaultConstraintOfConditionalType(type); } + function getConstraintOfConditionalType(type: ConditionalType) { + return hasNonCircularBaseConstraint(type) ? getConstraintFromConditionalType(type) : undefined; + } + function getUnionConstraintOfIntersection(type: IntersectionType, targetIsUnion: boolean) { let constraints: Type[] | undefined; let hasDisjointDomainType = false; @@ -7617,7 +7615,7 @@ namespace ts { if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) { return circularConstraintType; } - if (constraintDepth === 50) { + if (constraintDepth >= 50) { // We have reached 50 recursive invocations of getImmediateBaseConstraint and there is a // very high likelyhood we're dealing with an infinite generic type that perpetually generates // new type identities as we descend into it. We stop the recursion here and mark this type @@ -7684,8 +7682,11 @@ namespace ts { return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined; } if (t.flags & TypeFlags.Conditional) { - const constraint = getConstraintOfConditionalType(t); - return constraint && getBaseConstraint(constraint); + const constraint = getConstraintFromConditionalType(t); + constraintDepth++; // Penalize repeating conditional types (this captures the recursion within getConstraintFromConditionalType and carries it forward) + const result = constraint && getBaseConstraint(constraint); + constraintDepth--; + return result; } if (t.flags & TypeFlags.Substitution) { return getBaseConstraint((t).substitute); @@ -8866,6 +8867,9 @@ namespace ts { } function getSubstitutionType(typeVariable: TypeVariable, substitute: Type) { + if (substitute.flags & TypeFlags.AnyOrUnknown) { + return typeVariable; + } const result = createType(TypeFlags.Substitution); result.typeVariable = typeVariable; result.substitute = substitute; @@ -10161,7 +10165,7 @@ namespace ts { // Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`. if (falseType.flags & TypeFlags.Never && isTypeIdenticalTo(getActualTypeVariable(trueType), getActualTypeVariable(checkType))) { if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true - return getDefaultConstraintOfTrueBranchOfConditionalType(root, /*combinedMapper*/ undefined, mapper); + return trueType; } else if (isIntersectionEmpty(checkType, extendsType)) { // Always false return neverType; @@ -10172,7 +10176,7 @@ namespace ts { return neverType; } else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false - return falseType; // TODO: Intersect negated `extends` type here + return falseType; } } @@ -10227,21 +10231,15 @@ namespace ts { result.extendsType = extendsType; result.mapper = mapper; result.combinedMapper = combinedMapper; - if (!combinedMapper) { - result.resolvedTrueType = trueType; - result.resolvedFalseType = falseType; - } + result.resolvedTrueType = trueType; + result.resolvedFalseType = falseType; result.aliasSymbol = root.aliasSymbol; result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 return result; } - function getTrueTypeFromConditionalType(type: ConditionalType) { - return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(type.root.trueType, type.mapper)); - } - - function getFalseTypeFromConditionalType(type: ConditionalType) { - return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper)); + function getInferredTrueTypeFromConditionalType(type: ConditionalType) { + return type.inferredTrueType || (type.inferredTrueType = instantiateType(type.root.trueType, type.combinedMapper || type.mapper)); } function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined { @@ -11182,7 +11180,11 @@ namespace ts { return getSubstitutionType(maybeVariable as TypeVariable, instantiateType((type).substitute, mapper)); } else { - return maybeVariable; + const sub = instantiateType((type).substitute, mapper); + if (sub.flags & TypeFlags.AnyOrUnknown || isTypeSubtypeOf(maybeVariable, sub)) { + return maybeVariable; + } + return sub; } } return type; @@ -12706,8 +12708,8 @@ namespace ts { if ((source).root.isDistributive === (target).root.isDistributive) { if (result = isRelatedTo((source).checkType, (target).checkType, /*reportErrors*/ false)) { if (result &= isRelatedTo((source).extendsType, (target).extendsType, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).resolvedTrueType, (target).resolvedTrueType, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).resolvedFalseType, (target).resolvedFalseType, /*reportErrors*/ false)) { return result; } } @@ -12828,7 +12830,7 @@ namespace ts { return result; } } - const constraint = getConstraintOfType(source); + const constraint = getConstraintOfType(source); if (!constraint || (source.flags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) { // A type variable with no constraint is not related to the non-primitive object type. if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) { @@ -12860,8 +12862,8 @@ namespace ts { // and Y1 is related to Y2. if (isTypeIdenticalTo((source).extendsType, (target).extendsType) && (isRelatedTo((source).checkType, (target).checkType) || isRelatedTo((target).checkType, (source).checkType))) { - if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) { - result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), reportErrors); + if (result = isRelatedTo((source).resolvedTrueType, (target).resolvedTrueType, reportErrors)) { + result &= isRelatedTo((source).resolvedFalseType, (target).resolvedFalseType, reportErrors); } if (result) { errorInfo = saveErrorInfo; @@ -14696,12 +14698,12 @@ namespace ts { else if (source.flags & TypeFlags.Conditional && target.flags & TypeFlags.Conditional) { inferFromTypes((source).checkType, (target).checkType); inferFromTypes((source).extendsType, (target).extendsType); - inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target)); - inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target)); + inferFromTypes((source).resolvedTrueType, (target).resolvedTrueType); + inferFromTypes((source).resolvedFalseType, (target).resolvedFalseType); } else if (target.flags & TypeFlags.Conditional && !contravariant) { - inferFromTypes(source, getTrueTypeFromConditionalType(target)); - inferFromTypes(source, getFalseTypeFromConditionalType(target)); + inferFromTypes(source, (target).resolvedTrueType); + inferFromTypes(source, (target).resolvedFalseType); } else if (target.flags & TypeFlags.UnionOrIntersection) { for (const t of (target).types) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bc12adf004fb1..c98bf55013616 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4310,8 +4310,10 @@ namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType?: Type; - resolvedFalseType?: Type; + resolvedTrueType: Type; + resolvedFalseType: Type; + /* @internal */ + inferredTrueType?: Type; // The `trueType` instantiated with the `combinedMapper`, if present /* @internal */ resolvedDefaultConstraint?: Type; /* @internal */ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 59ae825a8dc80..a84867f52fd38 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2382,8 +2382,8 @@ declare namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType?: Type; - resolvedFalseType?: Type; + resolvedTrueType: Type; + resolvedFalseType: Type; } interface SubstitutionType extends InstantiableType { typeVariable: TypeVariable; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2b8056735a476..bec7f9faf9f45 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2382,8 +2382,8 @@ declare namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType?: Type; - resolvedFalseType?: Type; + resolvedTrueType: Type; + resolvedFalseType: Type; } interface SubstitutionType extends InstantiableType { typeVariable: TypeVariable; diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt new file mode 100644 index 0000000000000..8ae6eb886fdd4 --- /dev/null +++ b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt @@ -0,0 +1,97 @@ +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(33,13): error TS2456: Type alias 'Shared' circularly references itself. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(35,35): error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(35,35): error TS2315: Type 'Shared' is not generic. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,15): error TS2313: Type parameter 'P' has a circular constraint. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,76): error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,101): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,128): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(63,55): error TS2344: Type 'string | number | symbol' does not satisfy the constraint 'keyof GetProps'. + Type 'string' is not assignable to type 'keyof GetProps'. +tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(63,61): error TS2315: Type 'Shared' is not generic. + + +==== tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts (9 errors) ==== + declare class Component

{ + constructor(props: Readonly

); + constructor(props: P, context?: any); + readonly props: Readonly

& Readonly<{ children?: {} }>; + } + interface ComponentClass

{ + new (props: P, context?: any): Component

; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; + } + interface FunctionComponent

{ + (props: P & { children?: {} }, context?: any): {} | null; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; + } + + export declare const nominalTypeHack: unique symbol; + export interface Validator { + (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; + [nominalTypeHack]?: T; + } + type WeakValidationMap = { + [K in keyof T]?: null extends T[K] + ? Validator + : undefined extends T[K] + ? Validator + : Validator + }; + type ComponentType

= ComponentClass

| FunctionComponent

; + + export type Shared< + ~~~~~~ +!!! error TS2456: Type alias 'Shared' circularly references itself. + InjectedProps, + DecorationTargetProps extends Shared + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2315: Type 'Shared' is not generic. + > = { + [P in Extract]?: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2313: Type parameter 'P' has a circular constraint. +!!! related TS2751 tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts:35:35: Circularity originates in type at this location. + ~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. + }; + + // Infers prop type from component C + export type GetProps = C extends ComponentType ? P : never; + + export type ConnectedComponentClass< + C extends ComponentType, + P + > = ComponentClass

& { + WrappedComponent: C; + }; + + export type Matching = { + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P]; + }; + + export type Omit = Pick>; + + export type InferableComponentEnhancerWithProps = + >>>( + component: C + ) => ConnectedComponentClass, keyof Shared>> & TNeedsProps>; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'string | number | symbol' does not satisfy the constraint 'keyof GetProps'. +!!! error TS2344: Type 'string' is not assignable to type 'keyof GetProps'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2315: Type 'Shared' is not generic. + \ No newline at end of file diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types index 5bef1baa732a8..357f9195f3572 100644 --- a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types +++ b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types @@ -79,7 +79,7 @@ type ComponentType

= ComponentClass

| FunctionComponent

; >ComponentType : ComponentType

export type Shared< ->Shared : Shared +>Shared : any InjectedProps, DecorationTargetProps extends Shared diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt new file mode 100644 index 0000000000000..ef22bdb6f2faf --- /dev/null +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt @@ -0,0 +1,78 @@ +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(3,6): error TS2456: Type alias 'Shared' circularly references itself. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(5,35): error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(5,35): error TS2315: Type 'Shared' is not generic. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,15): error TS2313: Type parameter 'P' has a circular constraint. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,75): error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,100): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,127): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(15,16): error TS2315: Type 'Shared' is not generic. +tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(17,37): error TS2315: Type 'Shared' is not generic. + + +==== tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts (9 errors) ==== + type Omit = Pick>; + + type Shared< // Circularly self constraining type, defered thanks to mapping + ~~~~~~ +!!! error TS2456: Type alias 'Shared' circularly references itself. + InjectedProps, + DecorationTargetProps extends Shared + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2315: Type 'Shared' is not generic. + > = { + [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2313: Type parameter 'P' has a circular constraint. +!!! related TS2751 tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts:5:35: Circularity originates in type at this location. + ~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. + }; + + interface ComponentClass

{ + defaultProps?: Partial

; // Inference target is also mapped _and_ optional + } + + interface InferableComponentEnhancerWithProps { +

>( + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2315: Type 'Shared' is not generic. + component: ComponentClass

+ ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2315: Type 'Shared' is not generic. + } // Then intersected with and indexed via Omit and & + + interface Connect { // Then strictly compared with another signature in its context + ( + mapStateToProps: unknown, + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, + mapDispatchToProps: unknown, + mergeProps: null | undefined, + options: unknown + ): InferableComponentEnhancerWithProps; + } + + declare var connect: Connect; + + const myStoreConnect: Connect = function( + mapStateToProps?: any, + mapDispatchToProps?: any, + mergeProps?: any, + options: unknown = {}, + ) { + return connect( + mapStateToProps, + mapDispatchToProps, + mergeProps, + options, + ); + }; \ No newline at end of file diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types index 4a3a1fdbe53aa..74bdbec990ad4 100644 --- a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types @@ -3,7 +3,7 @@ type Omit = Pick>; >Omit : Pick> type Shared< // Circularly self constraining type, defered thanks to mapping ->Shared : Shared +>Shared : any InjectedProps, DecorationTargetProps extends Shared diff --git a/tests/baselines/reference/conditionalTypes1.js b/tests/baselines/reference/conditionalTypes1.js index b592bd33d10e8..5dc4851838467 100644 --- a/tests/baselines/reference/conditionalTypes1.js +++ b/tests/baselines/reference/conditionalTypes1.js @@ -509,8 +509,6 @@ declare function f5(p: K): Extract; declare let x0: { k: "a"; -} & { - k: "a"; a: number; }; declare type OptionsOfKind = Extract void), Function>; // string | numbe >T02 : string | number type T03 = Extract void), Function>; // () => void ->T03 : Function & (() => void) +>T03 : () => void type T04 = NonNullable; // string | number >T04 : string | number @@ -113,7 +113,7 @@ type T10 = Exclude; // { k: "c", c: boolean } >k : "a" | "b" type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string } ->T11 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; }) +>T11 : { k: "a"; a: number; } | { k: "b"; b: string; } >k : "a" | "b" type T12 = Exclude; // { k: "c", c: boolean } @@ -122,7 +122,7 @@ type T12 = Exclude; // { k: "c", c: boolean } >k : "b" type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string } ->T13 : ({ k: "a"; } & { k: "a"; a: number; }) | ({ k: "b"; } & { k: "a"; a: number; }) | ({ k: "a"; } & { k: "b"; b: string; }) | ({ k: "b"; } & { k: "b"; b: string; }) +>T13 : { k: "a"; a: number; } | { k: "b"; b: string; } >k : "a" >k : "b" @@ -140,8 +140,8 @@ declare function f5(p: K): Extractk : K let x0 = f5("a"); // { k: "a", a: number } ->x0 : { k: "a"; } & { k: "a"; a: number; } ->f5("a") : { k: "a"; } & { k: "a"; a: number; } +>x0 : { k: "a"; a: number; } +>f5("a") : { k: "a"; a: number; } >f5 : (p: K) => Extract >"a" : "a" @@ -150,13 +150,13 @@ type OptionsOfKind = Extract; >k : K type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } ->T16 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; }) +>T16 : { k: "a"; a: number; } | { k: "b"; b: string; } type Select = Extract; >Select : Extract type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } ->T17 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; }) +>T17 : { k: "a"; a: number; } | { k: "b"; b: string; } type TypeName = >TypeName : TypeName diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index 6cf81cf573039..ee7c10ada5891 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -21,13 +21,13 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS23 Type 'A' is not assignable to type 'B'. tests/cases/conformance/types/conditional/conditionalTypes2.ts(73,12): error TS2345: Argument of type 'Extract, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'. Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. - Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'. + Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'. Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. tests/cases/conformance/types/conditional/conditionalTypes2.ts(74,12): error TS2345: Argument of type 'Extract' is not assignable to parameter of type '{ foo: string; bat: string; }'. Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'. tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2' is not assignable to parameter of type '{ foo: string; bat: string; }'. Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'. - Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'. + Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. ==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (7 errors) ==== @@ -132,7 +132,7 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2 ~ !!! error TS2345: Argument of type 'Extract, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'. !!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. -!!! error TS2345: Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'. +!!! error TS2345: Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'. !!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. !!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here. !!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here. @@ -145,7 +145,8 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2 ~ !!! error TS2345: Argument of type 'Extract2' is not assignable to parameter of type '{ foo: string; bat: string; }'. !!! error TS2345: Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'. -!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'. +!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. +!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here. } // Repros from #22860 diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types index 7113ccc2be809..aac6ba47475c6 100644 --- a/tests/baselines/reference/conditionalTypes2.types +++ b/tests/baselines/reference/conditionalTypes2.types @@ -130,14 +130,14 @@ function f12(x: string | (() => string) | undefined) { >x : string | (() => string) | undefined const f = getFunction(x); // () => string ->f : Function & (() => string) ->getFunction(x) : Function & (() => string) +>f : () => string +>getFunction(x) : () => string >getFunction : (item: T) => Extract >x : string | (() => string) | undefined f(); >f() : string ->f : Function & (() => string) +>f : () => string } type Foo = { foo: string }; diff --git a/tests/baselines/reference/infiniteConstraints.errors.txt b/tests/baselines/reference/infiniteConstraints.errors.txt index a31bf10adb192..414fa8f9213a4 100644 --- a/tests/baselines/reference/infiniteConstraints.errors.txt +++ b/tests/baselines/reference/infiniteConstraints.errors.txt @@ -1,12 +1,13 @@ tests/cases/compiler/infiniteConstraints.ts(3,37): error TS2589: Type instantiation is excessively deep and possibly infinite. tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' cannot be used to index type 'B[Exclude]'. +tests/cases/compiler/infiniteConstraints.ts(21,21): error TS2536: Type '"val"' cannot be used to index type 'Extract>'. +tests/cases/compiler/infiniteConstraints.ts(21,57): error TS2536: Type '"val"' cannot be used to index type 'Extract], Record<"val", string>>'. tests/cases/compiler/infiniteConstraints.ts(31,43): error TS2322: Type 'Record<"val", "dup">' is not assignable to type 'never'. tests/cases/compiler/infiniteConstraints.ts(31,63): error TS2322: Type 'Record<"val", "dup">' is not assignable to type 'never'. tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'. -tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2589: Type instantiation is excessively deep and possibly infinite. -==== tests/cases/compiler/infiniteConstraints.ts (6 errors) ==== +==== tests/cases/compiler/infiniteConstraints.ts (7 errors) ==== // Both of the following types trigger the recursion limiter in getImmediateBaseConstraint type T1], { val: string }>["val"] }> = B; @@ -32,6 +33,10 @@ tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2589: Type instantia declare function ensureNoDuplicates< T extends { [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type '"val"' cannot be used to index type 'Extract>'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type '"val"' cannot be used to index type 'Extract], Record<"val", string>>'. ? never : any } @@ -55,6 +60,4 @@ tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2589: Type instantia declare function function1}>(): T[keyof T]["foo"]; ~~~~~~~~~~~~~~~~~ !!! error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'. - ~~~~~~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. \ No newline at end of file diff --git a/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.js b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.js new file mode 100644 index 0000000000000..c4bb71f2818b5 --- /dev/null +++ b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.js @@ -0,0 +1,10 @@ +//// [substitutionTypesCompareCorrectlyInRestrictiveInstances.ts] +type UnionKeys = T extends any ? keyof T : never; +type BugHelper = T extends any ? Exclude, keyof T> : never +type Bug = BugHelper +type Q = UnionKeys<{ a : any } | { b: any }> // should be "a" | "b" +type R = Bug<{ a : any } | { b: any }> // should be "a" | "b" + + +//// [substitutionTypesCompareCorrectlyInRestrictiveInstances.js] +"use strict"; diff --git a/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.symbols b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.symbols new file mode 100644 index 0000000000000..31f23823705d6 --- /dev/null +++ b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.symbols @@ -0,0 +1,36 @@ +=== tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts === +type UnionKeys = T extends any ? keyof T : never; +>UnionKeys : Symbol(UnionKeys, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 0)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 15)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 15)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 15)) + +type BugHelper = T extends any ? Exclude, keyof T> : never +>BugHelper : Symbol(BugHelper, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 52)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 15)) +>TAll : Symbol(TAll, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 17)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 15)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>UnionKeys : Symbol(UnionKeys, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 0)) +>TAll : Symbol(TAll, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 17)) +>T : Symbol(T, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 15)) + +type Bug = BugHelper +>Bug : Symbol(Bug, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 83)) +>TAll : Symbol(TAll, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 2, 9)) +>BugHelper : Symbol(BugHelper, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 52)) +>TAll : Symbol(TAll, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 2, 9)) +>TAll : Symbol(TAll, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 2, 9)) + +type Q = UnionKeys<{ a : any } | { b: any }> // should be "a" | "b" +>Q : Symbol(Q, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 2, 39)) +>UnionKeys : Symbol(UnionKeys, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 0, 0)) +>a : Symbol(a, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 3, 20)) +>b : Symbol(b, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 3, 34)) + +type R = Bug<{ a : any } | { b: any }> // should be "a" | "b" +>R : Symbol(R, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 3, 44)) +>Bug : Symbol(Bug, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 1, 83)) +>a : Symbol(a, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 4, 14)) +>b : Symbol(b, Decl(substitutionTypesCompareCorrectlyInRestrictiveInstances.ts, 4, 28)) + diff --git a/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.types b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.types new file mode 100644 index 0000000000000..f6c8eb08cd942 --- /dev/null +++ b/tests/baselines/reference/substitutionTypesCompareCorrectlyInRestrictiveInstances.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts === +type UnionKeys = T extends any ? keyof T : never; +>UnionKeys : UnionKeys + +type BugHelper = T extends any ? Exclude, keyof T> : never +>BugHelper : BugHelper + +type Bug = BugHelper +>Bug : BugHelper + +type Q = UnionKeys<{ a : any } | { b: any }> // should be "a" | "b" +>Q : "a" | "b" +>a : any +>b : any + +type R = Bug<{ a : any } | { b: any }> // should be "a" | "b" +>R : "a" | "b" +>a : any +>b : any + diff --git a/tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts b/tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts new file mode 100644 index 0000000000000..441c556e33127 --- /dev/null +++ b/tests/cases/compiler/substitutionTypesCompareCorrectlyInRestrictiveInstances.ts @@ -0,0 +1,6 @@ +// @strict: true +type UnionKeys = T extends any ? keyof T : never; +type BugHelper = T extends any ? Exclude, keyof T> : never +type Bug = BugHelper +type Q = UnionKeys<{ a : any } | { b: any }> // should be "a" | "b" +type R = Bug<{ a : any } | { b: any }> // should be "a" | "b" From d5f32bd7636d0fee1ae3632c40d21c560aa3222f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 25 Mar 2019 19:42:52 -0700 Subject: [PATCH 2/5] Strengthen supertype reduction check to reduce breakage --- src/compiler/checker.ts | 2 +- ...nalNoInfiniteInstantiationDepth.errors.txt | 97 ------------------- ...ditionalNoInfiniteInstantiationDepth.types | 2 +- ...plifyingConditionalTypesNoCrash.errors.txt | 78 --------------- ...lySimplifyingConditionalTypesNoCrash.types | 2 +- 5 files changed, 3 insertions(+), 178 deletions(-) delete mode 100644 tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt delete mode 100644 tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2cf6c59a3bc3a..e5ec251b19291 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11181,7 +11181,7 @@ namespace ts { } else { const sub = instantiateType((type).substitute, mapper); - if (sub.flags & TypeFlags.AnyOrUnknown || isTypeSubtypeOf(maybeVariable, sub)) { + if (sub.flags & TypeFlags.AnyOrUnknown || isTypeSubtypeOf(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) { return maybeVariable; } return sub; diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt deleted file mode 100644 index 8ae6eb886fdd4..0000000000000 --- a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt +++ /dev/null @@ -1,97 +0,0 @@ -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(33,13): error TS2456: Type alias 'Shared' circularly references itself. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(35,35): error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(35,35): error TS2315: Type 'Shared' is not generic. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,15): error TS2313: Type parameter 'P' has a circular constraint. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,76): error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,101): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(37,128): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(63,55): error TS2344: Type 'string | number | symbol' does not satisfy the constraint 'keyof GetProps'. - Type 'string' is not assignable to type 'keyof GetProps'. -tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(63,61): error TS2315: Type 'Shared' is not generic. - - -==== tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts (9 errors) ==== - declare class Component

{ - constructor(props: Readonly

); - constructor(props: P, context?: any); - readonly props: Readonly

& Readonly<{ children?: {} }>; - } - interface ComponentClass

{ - new (props: P, context?: any): Component

; - propTypes?: WeakValidationMap

; - defaultProps?: Partial

; - displayName?: string; - } - interface FunctionComponent

{ - (props: P & { children?: {} }, context?: any): {} | null; - propTypes?: WeakValidationMap

; - defaultProps?: Partial

; - displayName?: string; - } - - export declare const nominalTypeHack: unique symbol; - export interface Validator { - (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; - [nominalTypeHack]?: T; - } - type WeakValidationMap = { - [K in keyof T]?: null extends T[K] - ? Validator - : undefined extends T[K] - ? Validator - : Validator - }; - type ComponentType

= ComponentClass

| FunctionComponent

; - - export type Shared< - ~~~~~~ -!!! error TS2456: Type alias 'Shared' circularly references itself. - InjectedProps, - DecorationTargetProps extends Shared - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2315: Type 'Shared' is not generic. - > = { - [P in Extract]?: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2313: Type parameter 'P' has a circular constraint. -!!! related TS2751 tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts:35:35: Circularity originates in type at this location. - ~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. - }; - - // Infers prop type from component C - export type GetProps = C extends ComponentType ? P : never; - - export type ConnectedComponentClass< - C extends ComponentType, - P - > = ComponentClass

& { - WrappedComponent: C; - }; - - export type Matching = { - [P in keyof DecorationTargetProps]: P extends keyof InjectedProps - ? InjectedProps[P] extends DecorationTargetProps[P] - ? DecorationTargetProps[P] - : InjectedProps[P] - : DecorationTargetProps[P]; - }; - - export type Omit = Pick>; - - export type InferableComponentEnhancerWithProps = - >>>( - component: C - ) => ConnectedComponentClass, keyof Shared>> & TNeedsProps>; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2344: Type 'string | number | symbol' does not satisfy the constraint 'keyof GetProps'. -!!! error TS2344: Type 'string' is not assignable to type 'keyof GetProps'. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2315: Type 'Shared' is not generic. - \ No newline at end of file diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types index 357f9195f3572..5bef1baa732a8 100644 --- a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types +++ b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types @@ -79,7 +79,7 @@ type ComponentType

= ComponentClass

| FunctionComponent

; >ComponentType : ComponentType

export type Shared< ->Shared : any +>Shared : Shared InjectedProps, DecorationTargetProps extends Shared diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt deleted file mode 100644 index ef22bdb6f2faf..0000000000000 --- a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.errors.txt +++ /dev/null @@ -1,78 +0,0 @@ -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(3,6): error TS2456: Type alias 'Shared' circularly references itself. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(5,35): error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(5,35): error TS2315: Type 'Shared' is not generic. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,15): error TS2313: Type parameter 'P' has a circular constraint. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,75): error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,100): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(7,127): error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(15,16): error TS2315: Type 'Shared' is not generic. -tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts(17,37): error TS2315: Type 'Shared' is not generic. - - -==== tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts (9 errors) ==== - type Omit = Pick>; - - type Shared< // Circularly self constraining type, defered thanks to mapping - ~~~~~~ -!!! error TS2456: Type alias 'Shared' circularly references itself. - InjectedProps, - DecorationTargetProps extends Shared - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2313: Type parameter 'DecorationTargetProps' has a circular constraint. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2315: Type 'Shared' is not generic. - > = { - [P in Extract]: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2313: Type parameter 'P' has a circular constraint. -!!! related TS2751 tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts:5:35: Circularity originates in type at this location. - ~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'InjectedProps'. - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type 'P' cannot be used to index type 'DecorationTargetProps'. - }; - - interface ComponentClass

{ - defaultProps?: Partial

; // Inference target is also mapped _and_ optional - } - - interface InferableComponentEnhancerWithProps { -

>( - ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2315: Type 'Shared' is not generic. - component: ComponentClass

- ): ComponentClass> & TNeedsProps> & { WrappedComponent: ComponentClass

} - ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2315: Type 'Shared' is not generic. - } // Then intersected with and indexed via Omit and & - - interface Connect { // Then strictly compared with another signature in its context - ( - mapStateToProps: unknown, - ): InferableComponentEnhancerWithProps; - - ( - mapStateToProps: null | undefined, - mapDispatchToProps: unknown, - mergeProps: null | undefined, - options: unknown - ): InferableComponentEnhancerWithProps; - } - - declare var connect: Connect; - - const myStoreConnect: Connect = function( - mapStateToProps?: any, - mapDispatchToProps?: any, - mergeProps?: any, - options: unknown = {}, - ) { - return connect( - mapStateToProps, - mapDispatchToProps, - mergeProps, - options, - ); - }; \ No newline at end of file diff --git a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types index 74bdbec990ad4..4a3a1fdbe53aa 100644 --- a/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types +++ b/tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types @@ -3,7 +3,7 @@ type Omit = Pick>; >Omit : Pick> type Shared< // Circularly self constraining type, defered thanks to mapping ->Shared : any +>Shared : Shared InjectedProps, DecorationTargetProps extends Shared From d28ad011b063456b3599e159e4e80a5ccc490e00 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 26 Mar 2019 10:35:50 -0700 Subject: [PATCH 3/5] Rename conditional type fields per convention --- src/compiler/checker.ts | 28 +++++++++---------- src/compiler/types.ts | 6 ++-- .../reference/api/tsserverlibrary.d.ts | 4 +-- tests/baselines/reference/api/typescript.d.ts | 4 +-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e5ec251b19291..b652de00f858c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3492,8 +3492,8 @@ namespace ts { context.inferTypeParameters = (type).root.inferTypeParameters; const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context); context.inferTypeParameters = saveInferTypeParameters; - const trueTypeNode = typeToTypeNodeHelper((type).resolvedTrueType, context); - const falseTypeNode = typeToTypeNodeHelper((type).resolvedFalseType, context); + const trueTypeNode = typeToTypeNodeHelper((type).trueType, context); + const falseTypeNode = typeToTypeNodeHelper((type).falseType, context); context.approximateLength += 15; return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } @@ -7499,7 +7499,7 @@ namespace ts { // just `any`. This result is _usually_ unwanted - so instead here we elide an `any` branch from the constraint type, // in effect treating `any` like `never` rather than `unknown` in this location. const trueConstraint = getInferredTrueTypeFromConditionalType(type); - const falseConstraint = type.resolvedFalseType; + const falseConstraint = type.falseType; type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]); } return type.resolvedDefaultConstraint; @@ -10231,15 +10231,15 @@ namespace ts { result.extendsType = extendsType; result.mapper = mapper; result.combinedMapper = combinedMapper; - result.resolvedTrueType = trueType; - result.resolvedFalseType = falseType; + result.trueType = trueType; + result.falseType = falseType; result.aliasSymbol = root.aliasSymbol; result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 return result; } function getInferredTrueTypeFromConditionalType(type: ConditionalType) { - return type.inferredTrueType || (type.inferredTrueType = instantiateType(type.root.trueType, type.combinedMapper || type.mapper)); + return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = instantiateType(type.root.trueType, type.combinedMapper || type.mapper)); } function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined { @@ -12708,8 +12708,8 @@ namespace ts { if ((source).root.isDistributive === (target).root.isDistributive) { if (result = isRelatedTo((source).checkType, (target).checkType, /*reportErrors*/ false)) { if (result &= isRelatedTo((source).extendsType, (target).extendsType, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source).resolvedTrueType, (target).resolvedTrueType, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source).resolvedFalseType, (target).resolvedFalseType, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).trueType, (target).trueType, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source).falseType, (target).falseType, /*reportErrors*/ false)) { return result; } } @@ -12862,8 +12862,8 @@ namespace ts { // and Y1 is related to Y2. if (isTypeIdenticalTo((source).extendsType, (target).extendsType) && (isRelatedTo((source).checkType, (target).checkType) || isRelatedTo((target).checkType, (source).checkType))) { - if (result = isRelatedTo((source).resolvedTrueType, (target).resolvedTrueType, reportErrors)) { - result &= isRelatedTo((source).resolvedFalseType, (target).resolvedFalseType, reportErrors); + if (result = isRelatedTo((source).trueType, (target).trueType, reportErrors)) { + result &= isRelatedTo((source).falseType, (target).falseType, reportErrors); } if (result) { errorInfo = saveErrorInfo; @@ -14698,12 +14698,12 @@ namespace ts { else if (source.flags & TypeFlags.Conditional && target.flags & TypeFlags.Conditional) { inferFromTypes((source).checkType, (target).checkType); inferFromTypes((source).extendsType, (target).extendsType); - inferFromTypes((source).resolvedTrueType, (target).resolvedTrueType); - inferFromTypes((source).resolvedFalseType, (target).resolvedFalseType); + inferFromTypes((source).trueType, (target).trueType); + inferFromTypes((source).falseType, (target).falseType); } else if (target.flags & TypeFlags.Conditional && !contravariant) { - inferFromTypes(source, (target).resolvedTrueType); - inferFromTypes(source, (target).resolvedFalseType); + inferFromTypes(source, (target).trueType); + inferFromTypes(source, (target).falseType); } else if (target.flags & TypeFlags.UnionOrIntersection) { for (const t of (target).types) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c98bf55013616..bcc3218a017e7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4310,10 +4310,10 @@ namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType: Type; - resolvedFalseType: Type; + trueType: Type; + falseType: Type; /* @internal */ - inferredTrueType?: Type; // The `trueType` instantiated with the `combinedMapper`, if present + resolvedInferredTrueType?: Type; // The `trueType` instantiated with the `combinedMapper`, if present /* @internal */ resolvedDefaultConstraint?: Type; /* @internal */ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a84867f52fd38..8208cdba2ab46 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2382,8 +2382,8 @@ declare namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType: Type; - resolvedFalseType: Type; + trueType: Type; + falseType: Type; } interface SubstitutionType extends InstantiableType { typeVariable: TypeVariable; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index bec7f9faf9f45..314ccf298cf28 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2382,8 +2382,8 @@ declare namespace ts { root: ConditionalRoot; checkType: Type; extendsType: Type; - resolvedTrueType: Type; - resolvedFalseType: Type; + trueType: Type; + falseType: Type; } interface SubstitutionType extends InstantiableType { typeVariable: TypeVariable; From 73e3733d2528fde7415cabf912a689dc807d6740 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 26 Mar 2019 13:13:39 -0700 Subject: [PATCH 4/5] Explicitly handle anyish signatures in compareSignaturesRelated so strict variance doesnt kill subtyping --- src/compiler/checker.ts | 13 + ...uxLikeDeferredInferenceAllowsAssignment.js | 219 ++++++++ ...eDeferredInferenceAllowsAssignment.symbols | 471 ++++++++++++++++++ ...ikeDeferredInferenceAllowsAssignment.types | 288 +++++++++++ ...uxLikeDeferredInferenceAllowsAssignment.ts | 145 ++++++ 5 files changed, 1136 insertions(+) create mode 100644 tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.js create mode 100644 tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.symbols create mode 100644 tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.types create mode 100644 tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b652de00f858c..34391510b343a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11729,6 +11729,15 @@ namespace ts { type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void; + /** + * Returns true if `s` is `(...args: any[]) => any` or `(this: any, ...args: any[]) => any` + */ + function isAnySignature(s: Signature) { + return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 && + s.hasRestParameter && getTypeOfParameter(s.parameters[0]) === anyArrayType && + isTypeAny(getReturnTypeOfSignature(s)); + } + /** * See signatureRelatedTo, compareSignaturesIdentical */ @@ -11744,6 +11753,10 @@ namespace ts { return Ternary.True; } + if (isAnySignature(target)) { + return Ternary.True; + } + const targetCount = getParameterCount(target); if (!hasEffectiveRestParameter(target) && getMinArgumentCount(source) > targetCount) { return Ternary.False; diff --git a/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.js b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.js new file mode 100644 index 0000000000000..2eeda64fc989b --- /dev/null +++ b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.js @@ -0,0 +1,219 @@ +//// [reactReduxLikeDeferredInferenceAllowsAssignment.ts] +declare class Component

{ + constructor(props: Readonly

); + constructor(props: P, context?: any); + readonly props: Readonly

& Readonly<{ children?: {} }>; +} +interface ComponentClass

{ + new (props: P, context?: any): Component

; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; +} +interface FunctionComponent

{ + (props: P & { children?: {} }, context?: any): {} | null; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; +} + +declare const nominalTypeHack: unique symbol; +interface Validator { + ( + props: object, + propName: string, + componentName: string, + location: string, + propFullName: string + ): Error | null; + [nominalTypeHack]?: T; +} +type WeakValidationMap = { + [K in keyof T]?: null extends T[K] + ? Validator + : undefined extends T[K] + ? Validator + : Validator +}; +type ComponentType

= ComponentClass

| FunctionComponent

; + +type Shared< + InjectedProps, + DecorationTargetProps extends Shared +> = { + [P in Extract< + keyof InjectedProps, + keyof DecorationTargetProps + >]?: InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : never +}; + +// Infers prop type from component C +type GetProps = C extends ComponentType ? P : never; + +type ConnectedComponentClass, P> = ComponentClass< + P +> & { + WrappedComponent: C; +}; + +type Matching = { + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P] +}; + +type Omit = Pick>; + +type InferableComponentEnhancerWithProps = < + C extends ComponentType>> +>( + component: C +) => ConnectedComponentClass< + C, + Omit, keyof Shared>> & TNeedsProps +>; + +declare const connect: { + ( + mapStateToProps: null | undefined, + mapDispatchToProps: TDispatchProps + ): InferableComponentEnhancerWithProps< + ResolveThunks, + TOwnProps + >; +}; + +type InferThunkActionCreatorType< + TActionCreator extends (...args: any[]) => any +> = TActionCreator extends ( + ...args: infer TParams +) => (...args: any[]) => infer TReturn + ? (...args: TParams) => TReturn + : TActionCreator; + +type HandleThunkActionCreator = TActionCreator extends ( + ...args: any[] +) => any + ? InferThunkActionCreatorType + : TActionCreator; + +type ResolveThunks = TDispatchProps extends { + [key: string]: any; +} + ? { [C in keyof TDispatchProps]: HandleThunkActionCreator } + : TDispatchProps; + +interface Dispatch { + (action: T): T; +} +interface Action { + type: T; +} +interface AnyAction extends Action { + [extraProps: string]: any; +} + +const simpleAction = (payload: boolean) => ({ + type: "SIMPLE_ACTION", + payload +}); +const thunkAction = (param1: number, param2: string) => async ( + dispatch: Dispatch, + { foo }: OwnProps +) => { + return foo; +}; +interface OwnProps { + foo: string; +} +interface TestComponentProps extends OwnProps { + simpleAction: typeof simpleAction; + thunkAction(param1: number, param2: string): Promise; +} +class TestComponent extends Component {} +const mapDispatchToProps = { simpleAction, thunkAction }; + +type Q = HandleThunkActionCreator; + +const Test1 = connect( + null, + mapDispatchToProps +)(TestComponent); + + +//// [reactReduxLikeDeferredInferenceAllowsAssignment.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var _this = this; +var simpleAction = function (payload) { return ({ + type: "SIMPLE_ACTION", + payload: payload +}); }; +var thunkAction = function (param1, param2) { return function (dispatch, _a) { + var foo = _a.foo; + return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_b) { + return [2 /*return*/, foo]; + }); + }); +}; }; +var TestComponent = /** @class */ (function (_super) { + __extends(TestComponent, _super); + function TestComponent() { + return _super !== null && _super.apply(this, arguments) || this; + } + return TestComponent; +}(Component)); +var mapDispatchToProps = { simpleAction: simpleAction, thunkAction: thunkAction }; +var Test1 = connect(null, mapDispatchToProps)(TestComponent); diff --git a/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.symbols b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.symbols new file mode 100644 index 0000000000000..ec954dfde7951 --- /dev/null +++ b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.symbols @@ -0,0 +1,471 @@ +=== tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts === +declare class Component

{ +>Component : Symbol(Component, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 0)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 24)) + + constructor(props: Readonly

); +>props : Symbol(props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 1, 14)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 24)) + + constructor(props: P, context?: any); +>props : Symbol(props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 2, 14)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 24)) +>context : Symbol(context, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 2, 23)) + + readonly props: Readonly

& Readonly<{ children?: {} }>; +>props : Symbol(Component.props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 2, 39)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 24)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>children : Symbol(children, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 3, 42)) +} +interface ComponentClass

{ +>ComponentClass : Symbol(ComponentClass, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 4, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 5, 25)) + + new (props: P, context?: any): Component

; +>props : Symbol(props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 6, 7)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 5, 25)) +>context : Symbol(context, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 6, 16)) +>Component : Symbol(Component, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 0)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 5, 25)) + + propTypes?: WeakValidationMap

; +>propTypes : Symbol(ComponentClass.propTypes, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 6, 46)) +>WeakValidationMap : Symbol(WeakValidationMap, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 28, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 5, 25)) + + defaultProps?: Partial

; +>defaultProps : Symbol(ComponentClass.defaultProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 7, 35)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 5, 25)) + + displayName?: string; +>displayName : Symbol(ComponentClass.displayName, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 8, 28)) +} +interface FunctionComponent

{ +>FunctionComponent : Symbol(FunctionComponent, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 10, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 11, 28)) + + (props: P & { children?: {} }, context?: any): {} | null; +>props : Symbol(props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 12, 3)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 11, 28)) +>children : Symbol(children, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 12, 15)) +>context : Symbol(context, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 12, 32)) + + propTypes?: WeakValidationMap

; +>propTypes : Symbol(FunctionComponent.propTypes, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 12, 59)) +>WeakValidationMap : Symbol(WeakValidationMap, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 28, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 11, 28)) + + defaultProps?: Partial

; +>defaultProps : Symbol(FunctionComponent.defaultProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 13, 35)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 11, 28)) + + displayName?: string; +>displayName : Symbol(FunctionComponent.displayName, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 14, 28)) +} + +declare const nominalTypeHack: unique symbol; +>nominalTypeHack : Symbol(nominalTypeHack, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 13)) + +interface Validator { +>Validator : Symbol(Validator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 45)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 19, 20)) + + ( + props: object, +>props : Symbol(props, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 20, 3)) + + propName: string, +>propName : Symbol(propName, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 21, 18)) + + componentName: string, +>componentName : Symbol(componentName, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 22, 21)) + + location: string, +>location : Symbol(location, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 23, 26)) + + propFullName: string +>propFullName : Symbol(propFullName, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 24, 21)) + + ): Error | null; +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + [nominalTypeHack]?: T; +>[nominalTypeHack] : Symbol(Validator[nominalTypeHack], Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 26, 18)) +>nominalTypeHack : Symbol(nominalTypeHack, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 13)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 19, 20)) +} +type WeakValidationMap = { +>WeakValidationMap : Symbol(WeakValidationMap, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 28, 1)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) + + [K in keyof T]?: null extends T[K] +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) + + ? Validator +>Validator : Symbol(Validator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 45)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) + + : undefined extends T[K] +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) + + ? Validator +>Validator : Symbol(Validator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 45)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) + + : Validator +>Validator : Symbol(Validator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 18, 45)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 29, 23)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 30, 3)) + +}; +type ComponentType

= ComponentClass

| FunctionComponent

; +>ComponentType : Symbol(ComponentType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 35, 2)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 19)) +>ComponentClass : Symbol(ComponentClass, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 4, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 19)) +>FunctionComponent : Symbol(FunctionComponent, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 10, 1)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 19)) + +type Shared< +>Shared : Symbol(Shared, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 70)) + + InjectedProps, +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 38, 12)) + + DecorationTargetProps extends Shared +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 39, 16)) +>Shared : Symbol(Shared, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 70)) +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 38, 12)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 39, 16)) + +> = { + [P in Extract< +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 42, 3)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) + + keyof InjectedProps, +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 38, 12)) + + keyof DecorationTargetProps +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 39, 16)) + + >]?: InjectedProps[P] extends DecorationTargetProps[P] +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 38, 12)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 42, 3)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 39, 16)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 42, 3)) + + ? DecorationTargetProps[P] +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 39, 16)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 42, 3)) + + : never +}; + +// Infers prop type from component C +type GetProps = C extends ComponentType ? P : never; +>GetProps : Symbol(GetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 48, 2)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 14)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 14)) +>ComponentType : Symbol(ComponentType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 35, 2)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 48)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 48)) + +type ConnectedComponentClass, P> = ComponentClass< +>ConnectedComponentClass : Symbol(ConnectedComponentClass, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 64)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 53, 29)) +>ComponentType : Symbol(ComponentType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 35, 2)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 53, 58)) +>ComponentClass : Symbol(ComponentClass, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 4, 1)) + + P +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 53, 58)) + +> & { + WrappedComponent: C; +>WrappedComponent : Symbol(WrappedComponent, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 55, 5)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 53, 29)) + +}; + +type Matching = { +>Matching : Symbol(Matching, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 57, 2)) +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 14)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 28)) + + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 28)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 14)) + + ? InjectedProps[P] extends DecorationTargetProps[P] +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 14)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 28)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) + + ? DecorationTargetProps[P] +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 28)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) + + : InjectedProps[P] +>InjectedProps : Symbol(InjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 14)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) + + : DecorationTargetProps[P] +>DecorationTargetProps : Symbol(DecorationTargetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 59, 28)) +>P : Symbol(P, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 60, 3)) + +}; + +type Omit = Pick>; +>Omit : Symbol(Omit, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 65, 2)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 10)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 12)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 10)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 10)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 10)) +>K : Symbol(K, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 12)) + +type InferableComponentEnhancerWithProps = < +>InferableComponentEnhancerWithProps : Symbol(InferableComponentEnhancerWithProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 63)) +>TInjectedProps : Symbol(TInjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 41)) +>TNeedsProps : Symbol(TNeedsProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 56)) + + C extends ComponentType>> +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) +>ComponentType : Symbol(ComponentType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 35, 2)) +>Matching : Symbol(Matching, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 57, 2)) +>TInjectedProps : Symbol(TInjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 41)) +>GetProps : Symbol(GetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 48, 2)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) + +>( + component: C +>component : Symbol(component, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 71, 2)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) + +) => ConnectedComponentClass< +>ConnectedComponentClass : Symbol(ConnectedComponentClass, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 51, 64)) + + C, +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) + + Omit, keyof Shared>> & TNeedsProps +>Omit : Symbol(Omit, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 65, 2)) +>GetProps : Symbol(GetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 48, 2)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) +>Shared : Symbol(Shared, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 36, 70)) +>TInjectedProps : Symbol(TInjectedProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 41)) +>GetProps : Symbol(GetProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 48, 2)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 73)) +>TNeedsProps : Symbol(TNeedsProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 69, 56)) + +>; + +declare const connect: { +>connect : Symbol(connect, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 78, 13)) + + ( +>no_state : Symbol(no_state, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 3)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 17)) +>TOwnProps : Symbol(TOwnProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 38)) + + mapStateToProps: null | undefined, +>mapStateToProps : Symbol(mapStateToProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 55)) + + mapDispatchToProps: TDispatchProps +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 80, 38)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 17)) + + ): InferableComponentEnhancerWithProps< +>InferableComponentEnhancerWithProps : Symbol(InferableComponentEnhancerWithProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 67, 63)) + + ResolveThunks, +>ResolveThunks : Symbol(ResolveThunks, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 100, 19)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 17)) + + TOwnProps +>TOwnProps : Symbol(TOwnProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 79, 38)) + + >; +}; + +type InferThunkActionCreatorType< +>InferThunkActionCreatorType : Symbol(InferThunkActionCreatorType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 86, 2)) + + TActionCreator extends (...args: any[]) => any +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 88, 33)) +>args : Symbol(args, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 89, 26)) + +> = TActionCreator extends ( +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 88, 33)) + + ...args: infer TParams +>args : Symbol(args, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 90, 28)) +>TParams : Symbol(TParams, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 91, 16)) + +) => (...args: any[]) => infer TReturn +>args : Symbol(args, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 92, 6)) +>TReturn : Symbol(TReturn, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 92, 30)) + + ? (...args: TParams) => TReturn +>args : Symbol(args, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 93, 5)) +>TParams : Symbol(TParams, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 91, 16)) +>TReturn : Symbol(TReturn, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 92, 30)) + + : TActionCreator; +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 88, 33)) + +type HandleThunkActionCreator = TActionCreator extends ( +>HandleThunkActionCreator : Symbol(HandleThunkActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 94, 19)) +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 96, 30)) +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 96, 30)) + + ...args: any[] +>args : Symbol(args, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 96, 72)) + +) => any + ? InferThunkActionCreatorType +>InferThunkActionCreatorType : Symbol(InferThunkActionCreatorType, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 86, 2)) +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 96, 30)) + + : TActionCreator; +>TActionCreator : Symbol(TActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 96, 30)) + +type ResolveThunks = TDispatchProps extends { +>ResolveThunks : Symbol(ResolveThunks, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 100, 19)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 102, 19)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 102, 19)) + + [key: string]: any; +>key : Symbol(key, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 103, 3)) +} + ? { [C in keyof TDispatchProps]: HandleThunkActionCreator } +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 105, 7)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 102, 19)) +>HandleThunkActionCreator : Symbol(HandleThunkActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 94, 19)) +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 102, 19)) +>C : Symbol(C, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 105, 7)) + + : TDispatchProps; +>TDispatchProps : Symbol(TDispatchProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 102, 19)) + +interface Dispatch { +>Dispatch : Symbol(Dispatch, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 106, 19)) +>A : Symbol(A, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 108, 19)) +>Action : Symbol(Action, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 110, 1)) +>AnyAction : Symbol(AnyAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 113, 1)) + + (action: T): T; +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 109, 3)) +>A : Symbol(A, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 108, 19)) +>action : Symbol(action, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 109, 16)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 109, 3)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 109, 3)) +} +interface Action { +>Action : Symbol(Action, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 110, 1)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 111, 17)) + + type: T; +>type : Symbol(Action.type, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 111, 27)) +>T : Symbol(T, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 111, 17)) +} +interface AnyAction extends Action { +>AnyAction : Symbol(AnyAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 113, 1)) +>Action : Symbol(Action, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 110, 1)) + + [extraProps: string]: any; +>extraProps : Symbol(extraProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 115, 3)) +} + +const simpleAction = (payload: boolean) => ({ +>simpleAction : Symbol(simpleAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 118, 5)) +>payload : Symbol(payload, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 118, 22)) + + type: "SIMPLE_ACTION", +>type : Symbol(type, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 118, 45)) + + payload +>payload : Symbol(payload, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 119, 24)) + +}); +const thunkAction = (param1: number, param2: string) => async ( +>thunkAction : Symbol(thunkAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 122, 5)) +>param1 : Symbol(param1, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 122, 21)) +>param2 : Symbol(param2, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 122, 36)) + + dispatch: Dispatch, +>dispatch : Symbol(dispatch, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 122, 63)) +>Dispatch : Symbol(Dispatch, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 106, 19)) + + { foo }: OwnProps +>foo : Symbol(foo, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 124, 3)) +>OwnProps : Symbol(OwnProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 127, 2)) + +) => { + return foo; +>foo : Symbol(foo, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 124, 3)) + +}; +interface OwnProps { +>OwnProps : Symbol(OwnProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 127, 2)) + + foo: string; +>foo : Symbol(OwnProps.foo, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 128, 20)) +} +interface TestComponentProps extends OwnProps { +>TestComponentProps : Symbol(TestComponentProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 130, 1)) +>OwnProps : Symbol(OwnProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 127, 2)) + + simpleAction: typeof simpleAction; +>simpleAction : Symbol(TestComponentProps.simpleAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 131, 47)) +>simpleAction : Symbol(simpleAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 118, 5)) + + thunkAction(param1: number, param2: string): Promise; +>thunkAction : Symbol(TestComponentProps.thunkAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 132, 36)) +>param1 : Symbol(param1, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 133, 14)) +>param2 : Symbol(param2, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 133, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +} +class TestComponent extends Component {} +>TestComponent : Symbol(TestComponent, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 134, 1)) +>Component : Symbol(Component, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 0, 0)) +>TestComponentProps : Symbol(TestComponentProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 130, 1)) + +const mapDispatchToProps = { simpleAction, thunkAction }; +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 136, 5)) +>simpleAction : Symbol(simpleAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 136, 28)) +>thunkAction : Symbol(thunkAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 136, 42)) + +type Q = HandleThunkActionCreator; +>Q : Symbol(Q, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 136, 57)) +>HandleThunkActionCreator : Symbol(HandleThunkActionCreator, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 94, 19)) +>simpleAction : Symbol(simpleAction, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 118, 5)) + +const Test1 = connect( +>Test1 : Symbol(Test1, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 140, 5)) +>connect : Symbol(connect, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 78, 13)) + + null, + mapDispatchToProps +>mapDispatchToProps : Symbol(mapDispatchToProps, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 136, 5)) + +)(TestComponent); +>TestComponent : Symbol(TestComponent, Decl(reactReduxLikeDeferredInferenceAllowsAssignment.ts, 134, 1)) + diff --git a/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.types b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.types new file mode 100644 index 0000000000000..767d94535cbc9 --- /dev/null +++ b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.types @@ -0,0 +1,288 @@ +=== tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts === +declare class Component

{ +>Component : Component

+ + constructor(props: Readonly

); +>props : Readonly

+ + constructor(props: P, context?: any); +>props : P +>context : any + + readonly props: Readonly

& Readonly<{ children?: {} }>; +>props : Readonly

& Readonly<{ children?: {} | undefined; }> +>children : {} | undefined +} +interface ComponentClass

{ + new (props: P, context?: any): Component

; +>props : P +>context : any + + propTypes?: WeakValidationMap

; +>propTypes : WeakValidationMap

| undefined + + defaultProps?: Partial

; +>defaultProps : Partial

| undefined + + displayName?: string; +>displayName : string | undefined +} +interface FunctionComponent

{ + (props: P & { children?: {} }, context?: any): {} | null; +>props : P & { children?: {} | undefined; } +>children : {} | undefined +>context : any +>null : null + + propTypes?: WeakValidationMap

; +>propTypes : WeakValidationMap

| undefined + + defaultProps?: Partial

; +>defaultProps : Partial

| undefined + + displayName?: string; +>displayName : string | undefined +} + +declare const nominalTypeHack: unique symbol; +>nominalTypeHack : unique symbol + +interface Validator { + ( + props: object, +>props : object + + propName: string, +>propName : string + + componentName: string, +>componentName : string + + location: string, +>location : string + + propFullName: string +>propFullName : string + + ): Error | null; +>null : null + + [nominalTypeHack]?: T; +>[nominalTypeHack] : T | undefined +>nominalTypeHack : unique symbol +} +type WeakValidationMap = { +>WeakValidationMap : WeakValidationMap + + [K in keyof T]?: null extends T[K] +>null : null + + ? Validator +>null : null + + : undefined extends T[K] + ? Validator +>null : null + + : Validator +}; +type ComponentType

= ComponentClass

| FunctionComponent

; +>ComponentType : ComponentType

+ +type Shared< +>Shared : Shared + + InjectedProps, + DecorationTargetProps extends Shared +> = { + [P in Extract< + keyof InjectedProps, + keyof DecorationTargetProps + >]?: InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : never +}; + +// Infers prop type from component C +type GetProps = C extends ComponentType ? P : never; +>GetProps : GetProps + +type ConnectedComponentClass, P> = ComponentClass< +>ConnectedComponentClass : ConnectedComponentClass + + P +> & { + WrappedComponent: C; +>WrappedComponent : C + +}; + +type Matching = { +>Matching : Matching + + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P] +}; + +type Omit = Pick>; +>Omit : Pick> + +type InferableComponentEnhancerWithProps = < +>InferableComponentEnhancerWithProps : InferableComponentEnhancerWithProps + + C extends ComponentType>> +>( + component: C +>component : C + +) => ConnectedComponentClass< + C, + Omit, keyof Shared>> & TNeedsProps +>; + +declare const connect: { +>connect : (mapStateToProps: null | undefined, mapDispatchToProps: TDispatchProps) => InferableComponentEnhancerWithProps, TOwnProps> + + ( + mapStateToProps: null | undefined, +>mapStateToProps : null | undefined +>null : null + + mapDispatchToProps: TDispatchProps +>mapDispatchToProps : TDispatchProps + + ): InferableComponentEnhancerWithProps< + ResolveThunks, + TOwnProps + >; +}; + +type InferThunkActionCreatorType< +>InferThunkActionCreatorType : InferThunkActionCreatorType + + TActionCreator extends (...args: any[]) => any +>args : any[] + +> = TActionCreator extends ( + ...args: infer TParams +>args : TParams + +) => (...args: any[]) => infer TReturn +>args : any[] + + ? (...args: TParams) => TReturn +>args : TParams + + : TActionCreator; + +type HandleThunkActionCreator = TActionCreator extends ( +>HandleThunkActionCreator : HandleThunkActionCreator + + ...args: any[] +>args : any[] + +) => any + ? InferThunkActionCreatorType + : TActionCreator; + +type ResolveThunks = TDispatchProps extends { +>ResolveThunks : ResolveThunks + + [key: string]: any; +>key : string +} + ? { [C in keyof TDispatchProps]: HandleThunkActionCreator } + : TDispatchProps; + +interface Dispatch { + (action: T): T; +>action : T +} +interface Action { + type: T; +>type : T +} +interface AnyAction extends Action { + [extraProps: string]: any; +>extraProps : string +} + +const simpleAction = (payload: boolean) => ({ +>simpleAction : (payload: boolean) => { type: string; payload: boolean; } +>(payload: boolean) => ({ type: "SIMPLE_ACTION", payload}) : (payload: boolean) => { type: string; payload: boolean; } +>payload : boolean +>({ type: "SIMPLE_ACTION", payload}) : { type: string; payload: boolean; } +>{ type: "SIMPLE_ACTION", payload} : { type: string; payload: boolean; } + + type: "SIMPLE_ACTION", +>type : string +>"SIMPLE_ACTION" : "SIMPLE_ACTION" + + payload +>payload : boolean + +}); +const thunkAction = (param1: number, param2: string) => async ( +>thunkAction : (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise +>(param1: number, param2: string) => async ( dispatch: Dispatch, { foo }: OwnProps) => { return foo;} : (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise +>param1 : number +>param2 : string +>async ( dispatch: Dispatch, { foo }: OwnProps) => { return foo;} : (dispatch: Dispatch, { foo }: OwnProps) => Promise + + dispatch: Dispatch, +>dispatch : Dispatch + + { foo }: OwnProps +>foo : string + +) => { + return foo; +>foo : string + +}; +interface OwnProps { + foo: string; +>foo : string +} +interface TestComponentProps extends OwnProps { + simpleAction: typeof simpleAction; +>simpleAction : (payload: boolean) => { type: string; payload: boolean; } +>simpleAction : (payload: boolean) => { type: string; payload: boolean; } + + thunkAction(param1: number, param2: string): Promise; +>thunkAction : (param1: number, param2: string) => Promise +>param1 : number +>param2 : string +} +class TestComponent extends Component {} +>TestComponent : TestComponent +>Component : Component + +const mapDispatchToProps = { simpleAction, thunkAction }; +>mapDispatchToProps : { simpleAction: (payload: boolean) => { type: string; payload: boolean; }; thunkAction: (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise; } +>{ simpleAction, thunkAction } : { simpleAction: (payload: boolean) => { type: string; payload: boolean; }; thunkAction: (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise; } +>simpleAction : (payload: boolean) => { type: string; payload: boolean; } +>thunkAction : (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise + +type Q = HandleThunkActionCreator; +>Q : (payload: boolean) => { type: string; payload: boolean; } +>simpleAction : (payload: boolean) => { type: string; payload: boolean; } + +const Test1 = connect( +>Test1 : ConnectedComponentClass> +>connect( null, mapDispatchToProps)(TestComponent) : ConnectedComponentClass> +>connect( null, mapDispatchToProps) : InferableComponentEnhancerWithProps<{ simpleAction: (payload: boolean) => { type: string; payload: boolean; }; thunkAction: (param1: number, param2: string) => Promise; }, {}> +>connect : (mapStateToProps: null | undefined, mapDispatchToProps: TDispatchProps) => InferableComponentEnhancerWithProps, TOwnProps> + + null, +>null : null + + mapDispatchToProps +>mapDispatchToProps : { simpleAction: (payload: boolean) => { type: string; payload: boolean; }; thunkAction: (param1: number, param2: string) => (dispatch: Dispatch, { foo }: OwnProps) => Promise; } + +)(TestComponent); +>TestComponent : typeof TestComponent + diff --git a/tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts b/tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts new file mode 100644 index 0000000000000..940031c52c2e0 --- /dev/null +++ b/tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts @@ -0,0 +1,145 @@ +// @strict: true +declare class Component

{ + constructor(props: Readonly

); + constructor(props: P, context?: any); + readonly props: Readonly

& Readonly<{ children?: {} }>; +} +interface ComponentClass

{ + new (props: P, context?: any): Component

; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; +} +interface FunctionComponent

{ + (props: P & { children?: {} }, context?: any): {} | null; + propTypes?: WeakValidationMap

; + defaultProps?: Partial

; + displayName?: string; +} + +declare const nominalTypeHack: unique symbol; +interface Validator { + ( + props: object, + propName: string, + componentName: string, + location: string, + propFullName: string + ): Error | null; + [nominalTypeHack]?: T; +} +type WeakValidationMap = { + [K in keyof T]?: null extends T[K] + ? Validator + : undefined extends T[K] + ? Validator + : Validator +}; +type ComponentType

= ComponentClass

| FunctionComponent

; + +type Shared< + InjectedProps, + DecorationTargetProps extends Shared +> = { + [P in Extract< + keyof InjectedProps, + keyof DecorationTargetProps + >]?: InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : never +}; + +// Infers prop type from component C +type GetProps = C extends ComponentType ? P : never; + +type ConnectedComponentClass, P> = ComponentClass< + P +> & { + WrappedComponent: C; +}; + +type Matching = { + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P] +}; + +type Omit = Pick>; + +type InferableComponentEnhancerWithProps = < + C extends ComponentType>> +>( + component: C +) => ConnectedComponentClass< + C, + Omit, keyof Shared>> & TNeedsProps +>; + +declare const connect: { + ( + mapStateToProps: null | undefined, + mapDispatchToProps: TDispatchProps + ): InferableComponentEnhancerWithProps< + ResolveThunks, + TOwnProps + >; +}; + +type InferThunkActionCreatorType< + TActionCreator extends (...args: any[]) => any +> = TActionCreator extends ( + ...args: infer TParams +) => (...args: any[]) => infer TReturn + ? (...args: TParams) => TReturn + : TActionCreator; + +type HandleThunkActionCreator = TActionCreator extends ( + ...args: any[] +) => any + ? InferThunkActionCreatorType + : TActionCreator; + +type ResolveThunks = TDispatchProps extends { + [key: string]: any; +} + ? { [C in keyof TDispatchProps]: HandleThunkActionCreator } + : TDispatchProps; + +interface Dispatch { + (action: T): T; +} +interface Action { + type: T; +} +interface AnyAction extends Action { + [extraProps: string]: any; +} + +const simpleAction = (payload: boolean) => ({ + type: "SIMPLE_ACTION", + payload +}); +const thunkAction = (param1: number, param2: string) => async ( + dispatch: Dispatch, + { foo }: OwnProps +) => { + return foo; +}; +interface OwnProps { + foo: string; +} +interface TestComponentProps extends OwnProps { + simpleAction: typeof simpleAction; + thunkAction(param1: number, param2: string): Promise; +} +class TestComponent extends Component {} +const mapDispatchToProps = { simpleAction, thunkAction }; + +type Q = HandleThunkActionCreator; + +const Test1 = connect( + null, + mapDispatchToProps +)(TestComponent); From 34cc42758e1942efc54118b88be58dcf9a5a112f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 27 Mar 2019 10:50:11 -0700 Subject: [PATCH 5/5] Allow tuple expansions to an `any` rest to be considered an `any` signature as well --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34391510b343a..98a459b6ccd3d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11734,7 +11734,7 @@ namespace ts { */ function isAnySignature(s: Signature) { return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 && - s.hasRestParameter && getTypeOfParameter(s.parameters[0]) === anyArrayType && + s.hasRestParameter && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) && isTypeAny(getReturnTypeOfSignature(s)); }