Skip to content
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
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40002,7 +40002,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (type.flags & TypeFlags.UnionOrIntersection) {
const types = (type as UnionOrIntersectionType).types;
for (const t of types) {
if (maybeTypeOfKind(t, kind)) {
if (maybeTypeOfKind(isNoInferType(t) ? (t as SubstitutionType).baseType : t, kind)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferIntersectedWithEmptyObjectKeyof1.ts] ////

=== noInferIntersectedWithEmptyObjectKeyof1.ts ===
// https://github.com/microsoft/TypeScript/issues/61091

type Keys = keyof (NoInfer<{ foo: string }> & {}); // "foo"
>Keys : Symbol(Keys, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 0, 0))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>foo : Symbol(foo, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 2, 28))

type LowInfer<T> = T & {};
>LowInfer : Symbol(LowInfer, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 2, 50))
>T : Symbol(T, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 4, 14))
>T : Symbol(T, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 4, 14))

type PropertyAssigner<TContext> = {
>PropertyAssigner : Symbol(PropertyAssigner, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 4, 26))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 5, 22))

[K in keyof TContext]?: (context: TContext) => TContext[K];
>K : Symbol(K, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 6, 3))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 5, 22))
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 6, 27))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 5, 22))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 5, 22))
>K : Symbol(K, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 6, 3))

};
type Source = {
>Source : Symbol(Source, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 7, 2))

count: () => number;
>count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 8, 15))

};
type Target = PropertyAssigner<LowInfer<NoInfer<{ count: number }>>>;
>Target : Symbol(Target, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 10, 2))
>PropertyAssigner : Symbol(PropertyAssigner, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 4, 26))
>LowInfer : Symbol(LowInfer, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 2, 50))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 11, 49))

declare const source: Source;
>source : Symbol(source, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 12, 13))
>Source : Symbol(Source, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 7, 2))

const target: Target = source; // ok
>target : Symbol(target, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 13, 5))
>Target : Symbol(Target, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 10, 2))
>source : Symbol(source, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 12, 13))

type ActionFunction<TContext> = {
>ActionFunction : Symbol(ActionFunction, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 13, 30))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 15, 20))

(args: { context: TContext }): void;
>args : Symbol(args, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 16, 3))
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 16, 10))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 15, 20))

_out_TContext?: TContext;
>_out_TContext : Symbol(_out_TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 16, 38))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 15, 20))

};

type TransitionsConfig<TContext> = Record<
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 18, 2))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 20, 23))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

string,
{
actions?: ActionFunction<TContext>;
>actions : Symbol(actions, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 22, 3))
>ActionFunction : Symbol(ActionFunction, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 13, 30))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 20, 23))
}
>;

declare function assign<TContext>(
>assign : Symbol(assign, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 25, 2))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 27, 24))

assignment: PropertyAssigner<LowInfer<TContext>>,
>assignment : Symbol(assignment, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 27, 34))
>PropertyAssigner : Symbol(PropertyAssigner, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 4, 26))
>LowInfer : Symbol(LowInfer, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 2, 50))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 27, 24))

): ActionFunction<TContext>;
>ActionFunction : Symbol(ActionFunction, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 13, 30))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 27, 24))

declare function createMachine<TContext>(config: {
>createMachine : Symbol(createMachine, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 29, 28))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 31, 31))
>config : Symbol(config, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 31, 41))

types?: {
>types : Symbol(types, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 31, 50))

context?: TContext;
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 32, 11))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 31, 31))

};
on?: TransitionsConfig<NoInfer<TContext>>;
>on : Symbol(on, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 34, 4))
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 18, 2))
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
>TContext : Symbol(TContext, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 31, 31))

}): void;

createMachine({
>createMachine : Symbol(createMachine, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 29, 28))

types: {
>types : Symbol(types, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 38, 15))

context: {
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 39, 10))

count: 0,
>count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 40, 14))

},
},
on: {
>on : Symbol(on, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 43, 4))

FOO: {
>FOO : Symbol(FOO, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 44, 7))

actions: assign({
>actions : Symbol(actions, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 45, 10))
>assign : Symbol(assign, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 25, 2))

count: (context) => context.count + 1,
>count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 46, 23))
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 47, 16))
>context.count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 40, 14))
>context : Symbol(context, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 47, 16))
>count : Symbol(count, Decl(noInferIntersectedWithEmptyObjectKeyof1.ts, 40, 14))

}),
},
},
});

Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferIntersectedWithEmptyObjectKeyof1.ts] ////

=== noInferIntersectedWithEmptyObjectKeyof1.ts ===
// https://github.com/microsoft/TypeScript/issues/61091

type Keys = keyof (NoInfer<{ foo: string }> & {}); // "foo"
>Keys : "foo"
> : ^^^^^
>foo : string
> : ^^^^^^

type LowInfer<T> = T & {};
>LowInfer : LowInfer<T>
> : ^^^^^^^^^^^

type PropertyAssigner<TContext> = {
>PropertyAssigner : PropertyAssigner<TContext>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^

[K in keyof TContext]?: (context: TContext) => TContext[K];
>context : TContext
> : ^^^^^^^^

};
type Source = {
>Source : Source
> : ^^^^^^

count: () => number;
>count : () => number
> : ^^^^^^

};
type Target = PropertyAssigner<LowInfer<NoInfer<{ count: number }>>>;
>Target : PropertyAssigner<LowInfer<NoInfer<{ count: number; }>>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
>count : number
> : ^^^^^^

declare const source: Source;
>source : Source
> : ^^^^^^

const target: Target = source; // ok
>target : PropertyAssigner<LowInfer<NoInfer<{ count: number; }>>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
>source : Source
> : ^^^^^^

type ActionFunction<TContext> = {
>ActionFunction : ActionFunction<TContext>
> : ^^^^^^^^^^^^^^^^^^^^^^^^

(args: { context: TContext }): void;
>args : { context: TContext; }
> : ^^^^^^^^^^^ ^^^
>context : TContext
> : ^^^^^^^^

_out_TContext?: TContext;
>_out_TContext : TContext | undefined
> : ^^^^^^^^^^^^^^^^^^^^

};

type TransitionsConfig<TContext> = Record<
>TransitionsConfig : TransitionsConfig<TContext>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^

string,
{
actions?: ActionFunction<TContext>;
>actions : ActionFunction<TContext> | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
>;

declare function assign<TContext>(
>assign : <TContext>(assignment: PropertyAssigner<LowInfer<TContext>>) => ActionFunction<TContext>
> : ^ ^^ ^^ ^^^^^

assignment: PropertyAssigner<LowInfer<TContext>>,
>assignment : PropertyAssigner<LowInfer<TContext>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

): ActionFunction<TContext>;

declare function createMachine<TContext>(config: {
>createMachine : <TContext>(config: { types?: { context?: TContext; }; on?: TransitionsConfig<NoInfer<TContext>>; }) => void
> : ^ ^^ ^^ ^^^^^
>config : { types?: { context?: TContext; }; on?: TransitionsConfig<NoInfer<TContext>>; }
> : ^^^^^^^^^^ ^^^^^^^ ^^^

types?: {
>types : { context?: TContext; } | undefined
> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^

context?: TContext;
>context : TContext | undefined
> : ^^^^^^^^^^^^^^^^^^^^

};
on?: TransitionsConfig<NoInfer<TContext>>;
>on : TransitionsConfig<NoInfer<TContext>> | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

}): void;

createMachine({
>createMachine({ types: { context: { count: 0, }, }, on: { FOO: { actions: assign({ count: (context) => context.count + 1, }), }, },}) : void
> : ^^^^
>createMachine : <TContext>(config: { types?: { context?: TContext; }; on?: TransitionsConfig<NoInfer<TContext>>; }) => void
> : ^ ^^ ^^ ^^^^^
>{ types: { context: { count: 0, }, }, on: { FOO: { actions: assign({ count: (context) => context.count + 1, }), }, },} : { types: { context: { count: number; }; }; on: { FOO: { actions: ActionFunction<NoInfer<{ count: number; }>>; }; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

types: {
>types : { context: { count: number; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ context: { count: 0, }, } : { context: { count: number; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

context: {
>context : { count: number; }
> : ^^^^^^^^^^^^^^^^^^
>{ count: 0, } : { count: number; }
> : ^^^^^^^^^^^^^^^^^^

count: 0,
>count : number
> : ^^^^^^
>0 : 0
> : ^

},
},
on: {
>on : { FOO: { actions: ActionFunction<NoInfer<{ count: number; }>>; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ FOO: { actions: assign({ count: (context) => context.count + 1, }), }, } : { FOO: { actions: ActionFunction<NoInfer<{ count: number; }>>; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

FOO: {
>FOO : { actions: ActionFunction<NoInfer<{ count: number; }>>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ actions: assign({ count: (context) => context.count + 1, }), } : { actions: ActionFunction<NoInfer<{ count: number; }>>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

actions: assign({
>actions : ActionFunction<NoInfer<{ count: number; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>assign({ count: (context) => context.count + 1, }) : ActionFunction<NoInfer<{ count: number; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>assign : <TContext>(assignment: PropertyAssigner<LowInfer<TContext>>) => ActionFunction<TContext>
> : ^ ^^ ^^ ^^^^^
>{ count: (context) => context.count + 1, } : { count: (context: LowInfer<NoInfer<{ count: number; }>>) => number; }
> : ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

count: (context) => context.count + 1,
>count : (context: LowInfer<NoInfer<{ count: number; }>>) => number
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(context) => context.count + 1 : (context: LowInfer<NoInfer<{ count: number; }>>) => number
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>context : LowInfer<NoInfer<{ count: number; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>context.count + 1 : number
> : ^^^^^^
>context.count : number
> : ^^^^^^
>context : LowInfer<NoInfer<{ count: number; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>count : number
> : ^^^^^^
>1 : 1
> : ^

}),
},
},
});

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// @strict: true
// @noEmit: true

// https://github.com/microsoft/TypeScript/issues/61091

type Keys = keyof (NoInfer<{ foo: string }> & {}); // "foo"

type LowInfer<T> = T & {};
type PropertyAssigner<TContext> = {
[K in keyof TContext]?: (context: TContext) => TContext[K];
};
type Source = {
count: () => number;
};
type Target = PropertyAssigner<LowInfer<NoInfer<{ count: number }>>>;
declare const source: Source;
const target: Target = source; // ok

type ActionFunction<TContext> = {
(args: { context: TContext }): void;
_out_TContext?: TContext;
};

type TransitionsConfig<TContext> = Record<
string,
{
actions?: ActionFunction<TContext>;
}
>;

declare function assign<TContext>(
assignment: PropertyAssigner<LowInfer<TContext>>,
): ActionFunction<TContext>;

declare function createMachine<TContext>(config: {
types?: {
context?: TContext;
};
on?: TransitionsConfig<NoInfer<TContext>>;
}): void;

createMachine({
types: {
context: {
count: 0,
},
},
on: {
FOO: {
actions: assign({
count: (context) => context.count + 1,
}),
},
},
});