Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit circular references in type arguments for object type aliases #57293

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 99 additions & 46 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

68 changes: 38 additions & 30 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6280,27 +6280,28 @@ export const enum ObjectFlags {
Tuple = 1 << 3, // Synthesized generic tuple type
Anonymous = 1 << 4, // Anonymous
Mapped = 1 << 5, // Mapped
Instantiated = 1 << 6, // Instantiated anonymous or mapped type
ObjectLiteral = 1 << 7, // Originates in an object literal
EvolvingArray = 1 << 8, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
ReverseMapped = 1 << 10, // Object contains a property from a reverse-mapped type
JsxAttributes = 1 << 11, // Jsx attributes type
JSLiteral = 1 << 12, // Object type declared in JS - disables errors on read/write of nonexisting members
FreshLiteral = 1 << 13, // Fresh object literal
ArrayLiteral = 1 << 14, // Originates in an array literal
TypeAliasInstantiation = 1 << 6, // Deferred type alias instantiation
Instantiated = 1 << 7, // Instantiated anonymous or mapped type
ObjectLiteral = 1 << 8, // Originates in an object literal
EvolvingArray = 1 << 9, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 10, // Object literal pattern with computed properties
ReverseMapped = 1 << 11, // Object contains a property from a reverse-mapped type
JsxAttributes = 1 << 12, // Jsx attributes type
JSLiteral = 1 << 13, // Object type declared in JS - disables errors on read/write of nonexisting members
FreshLiteral = 1 << 14, // Fresh object literal
ArrayLiteral = 1 << 15, // Originates in an array literal
/** @internal */
PrimitiveUnion = 1 << 15, // Union of only primitive types
PrimitiveUnion = 1 << 16, // Union of only primitive types
/** @internal */
ContainsWideningType = 1 << 16, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 17, // Type is or contains undefined or null widening type
/** @internal */
ContainsObjectOrArrayLiteral = 1 << 17, // Type is or contains object literal type
ContainsObjectOrArrayLiteral = 1 << 18, // Type is or contains object literal type
/** @internal */
NonInferrableType = 1 << 18, // Type is or contains anyFunctionType or silentNeverType
NonInferrableType = 1 << 19, // Type is or contains anyFunctionType or silentNeverType
/** @internal */
CouldContainTypeVariablesComputed = 1 << 19, // CouldContainTypeVariables flag has been computed
CouldContainTypeVariablesComputed = 1 << 20, // CouldContainTypeVariables flag has been computed
/** @internal */
CouldContainTypeVariables = 1 << 20, // Type could contain a type variable
CouldContainTypeVariables = 1 << 21, // Type could contain a type variable

ClassOrInterface = Class | Interface,
/** @internal */
Expand All @@ -6314,43 +6315,43 @@ export const enum ObjectFlags {
ObjectTypeKindMask = ClassOrInterface | Reference | Tuple | Anonymous | Mapped | ReverseMapped | EvolvingArray,

// Flags that require TypeFlags.Object
ContainsSpread = 1 << 21, // Object literal contains spread operation
ObjectRestType = 1 << 22, // Originates in object rest declaration
InstantiationExpressionType = 1 << 23, // Originates in instantiation expression
ContainsSpread = 1 << 22, // Object literal contains spread operation
ObjectRestType = 1 << 23, // Originates in object rest declaration
InstantiationExpressionType = 1 << 24, // Originates in instantiation expression
/** @internal */
IsClassInstanceClone = 1 << 24, // Type is a clone of a class instance type
IsClassInstanceClone = 1 << 25, // Type is a clone of a class instance type
// Flags that require TypeFlags.Object and ObjectFlags.Reference
/** @internal */
IdenticalBaseTypeCalculated = 1 << 25, // has had `getSingleBaseForNonAugmentingSubtype` invoked on it already
IdenticalBaseTypeCalculated = 1 << 26, // has had `getSingleBaseForNonAugmentingSubtype` invoked on it already
/** @internal */
IdenticalBaseTypeExists = 1 << 26, // has a defined cachedEquivalentBaseType member
IdenticalBaseTypeExists = 1 << 27, // has a defined cachedEquivalentBaseType member

// Flags that require TypeFlags.UnionOrIntersection or TypeFlags.Substitution
/** @internal */
IsGenericTypeComputed = 1 << 21, // IsGenericObjectType flag has been computed
IsGenericTypeComputed = 1 << 22, // IsGenericObjectType flag has been computed
/** @internal */
IsGenericObjectType = 1 << 22, // Union or intersection contains generic object type
IsGenericObjectType = 1 << 23, // Union or intersection contains generic object type
/** @internal */
IsGenericIndexType = 1 << 23, // Union or intersection contains generic index type
IsGenericIndexType = 1 << 24, // Union or intersection contains generic index type
/** @internal */
IsGenericType = IsGenericObjectType | IsGenericIndexType,

// Flags that require TypeFlags.Union
/** @internal */
ContainsIntersections = 1 << 24, // Union contains intersections
ContainsIntersections = 1 << 25, // Union contains intersections
/** @internal */
IsUnknownLikeUnionComputed = 1 << 25, // IsUnknownLikeUnion flag has been computed
IsUnknownLikeUnionComputed = 1 << 26, // IsUnknownLikeUnion flag has been computed
/** @internal */
IsUnknownLikeUnion = 1 << 26, // Union of null, undefined, and empty object type
IsUnknownLikeUnion = 1 << 27, // Union of null, undefined, and empty object type
/** @internal */

// Flags that require TypeFlags.Intersection
/** @internal */
IsNeverIntersectionComputed = 1 << 24, // IsNeverLike flag has been computed
IsNeverIntersectionComputed = 1 << 25, // IsNeverLike flag has been computed
/** @internal */
IsNeverIntersection = 1 << 25, // Intersection reduces to never
IsNeverIntersection = 1 << 26, // Intersection reduces to never
/** @internal */
IsConstrainedTypeVariable = 1 << 26, // T & C, where T's constraint and C are primitives, object, or {}
IsConstrainedTypeVariable = 1 << 27, // T & C, where T's constraint and C are primitives, object, or {}
}

/** @internal */
Expand Down Expand Up @@ -6544,6 +6545,13 @@ export interface MappedType extends AnonymousType {
containsError?: boolean;
}

/** @internal */
export interface TypeAliasInstantiationType extends AnonymousType {
typeAlias: Symbol; // Type alias symbol
node: NodeWithTypeArguments; // Type alias instantiation node
resolvedType?: ObjectType; // Resolved type alias instantiation
}

export interface EvolvingArrayType extends ObjectType {
elementType: Type; // Element expressions of evolving array type
finalArrayType?: Type; // Final array type of evolving array type
Expand Down
25 changes: 13 additions & 12 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7240,19 +7240,20 @@ declare namespace ts {
Tuple = 8,
Anonymous = 16,
Mapped = 32,
Instantiated = 64,
ObjectLiteral = 128,
EvolvingArray = 256,
ObjectLiteralPatternWithComputedProperties = 512,
ReverseMapped = 1024,
JsxAttributes = 2048,
JSLiteral = 4096,
FreshLiteral = 8192,
ArrayLiteral = 16384,
TypeAliasInstantiation = 64,
Instantiated = 128,
ObjectLiteral = 256,
EvolvingArray = 512,
ObjectLiteralPatternWithComputedProperties = 1024,
ReverseMapped = 2048,
JsxAttributes = 4096,
JSLiteral = 8192,
FreshLiteral = 16384,
ArrayLiteral = 32768,
ClassOrInterface = 3,
ContainsSpread = 2097152,
ObjectRestType = 4194304,
InstantiationExpressionType = 8388608,
ContainsSpread = 4194304,
ObjectRestType = 8388608,
InstantiationExpressionType = 16777216,
}
interface ObjectType extends Type {
objectFlags: ObjectFlags;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ declare var connect: Connect;

const myStoreConnect: Connect = function(
>myStoreConnect : Connect
>function( mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options: unknown = {},) { return connect( mapStateToProps, mapDispatchToProps, mergeProps, options, );} : <TStateProps, TOwnProps>(mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options?: unknown) => InferableComponentEnhancerWithProps<TStateProps, Omit<P, Extract<keyof TStateProps, keyof P>> & TOwnProps>
>function( mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options: unknown = {},) { return connect( mapStateToProps, mapDispatchToProps, mergeProps, options, );} : <TStateProps, TOwnProps>(mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options?: unknown) => InferableComponentEnhancerWithProps<TStateProps, TOwnProps>

mapStateToProps?: any,
>mapStateToProps : any
Expand All @@ -73,7 +73,7 @@ const myStoreConnect: Connect = function(

) {
return connect(
>connect( mapStateToProps, mapDispatchToProps, mergeProps, options, ) : InferableComponentEnhancerWithProps<TStateProps, Omit<P, Extract<keyof TStateProps, keyof P>> & TOwnProps>
>connect( mapStateToProps, mapDispatchToProps, mergeProps, options, ) : InferableComponentEnhancerWithProps<TStateProps, TOwnProps>
>connect : Connect

mapStateToProps,
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/omitTypeTestErrors01.types
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface Foo {
}

export type Bar = Omit<Foo, "c">;
>Bar : { a: string; b: number; }
>Bar : { b: number; a: string; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why'd this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to do with the order in which the literal types were materialized. Because we defer the Omit instantiations, we end up materializing the "b" and "c" literal types before we materialize "a". Since Omit is non-homomorphic and since unions are ordered by type ID, this ends up flipping the properties.


export type Baz = Omit<Foo, "b" | "c">;
>Baz : { a: string; }
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/omitTypeTests01.types
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface Foo {
}

export type Bar = Omit<Foo, "c">;
>Bar : { a: string; b: number; }
>Bar : { b: number; a: string; }

export type Baz = Omit<Foo, "b" | "c">;
>Baz : { a: string; }
Expand Down
Loading