Fixed incorrect SignatureFlags.HasRestParameter propagation when combining signatures (#58440)

This commit is contained in:
Mateusz Burzyński 2024-09-25 22:21:41 +02:00 committed by GitHub
parent 413f0fa831
commit 55886a1e24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1689 additions and 3 deletions

View File

@ -14032,8 +14032,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
paramMapper = createTypeMapper(right.typeParameters, left.typeParameters);
// We just use the type parameter defaults from the first signature
}
let flags = (left.flags | right.flags) & (SignatureFlags.PropagatingFlags & ~SignatureFlags.HasRestParameter);
const declaration = left.declaration;
const params = combineUnionParameters(left, right, paramMapper);
const lastParam = lastOrUndefined(params);
if (lastParam && getCheckFlags(lastParam) & CheckFlags.RestParameter) {
flags |= SignatureFlags.HasRestParameter;
}
const thisParam = combineUnionThisParam(left.thisParameter, right.thisParameter, paramMapper);
const minArgCount = Math.max(left.minArgumentCount, right.minArgumentCount);
const result = createSignature(
@ -14044,7 +14049,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
/*resolvedReturnType*/ undefined,
/*resolvedTypePredicate*/ undefined,
minArgCount,
(left.flags | right.flags) & SignatureFlags.PropagatingFlags,
flags,
);
result.compositeKind = TypeFlags.Union;
result.compositeSignatures = concatenate(left.compositeKind !== TypeFlags.Intersection && left.compositeSignatures || [left], [right]);
@ -32545,12 +32550,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const paramSymbol = createSymbol(
SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0),
paramName || `arg${i}` as __String,
isRestParam ? CheckFlags.RestParameter : isOptional ? CheckFlags.OptionalParameter : 0,
);
paramSymbol.links.type = isRestParam ? createArrayType(unionParamType) : unionParamType;
params[i] = paramSymbol;
}
if (needsExtraRestElement) {
const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String);
const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String, CheckFlags.RestParameter);
restParamSymbol.links.type = createArrayType(getTypeAtPosition(shorter, longestCount));
if (shorter === right) {
restParamSymbol.links.type = instantiateType(restParamSymbol.links.type, mapper);
@ -32567,8 +32573,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
paramMapper = createTypeMapper(right.typeParameters, left.typeParameters);
// We just use the type parameter defaults from the first signature
}
let flags = (left.flags | right.flags) & (SignatureFlags.PropagatingFlags & ~SignatureFlags.HasRestParameter);
const declaration = left.declaration;
const params = combineIntersectionParameters(left, right, paramMapper);
const lastParam = lastOrUndefined(params);
if (lastParam && getCheckFlags(lastParam) & CheckFlags.RestParameter) {
flags |= SignatureFlags.HasRestParameter;
}
const thisParam = combineIntersectionThisParam(left.thisParameter, right.thisParameter, paramMapper);
const minArgCount = Math.max(left.minArgumentCount, right.minArgumentCount);
const result = createSignature(
@ -32579,7 +32590,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
/*resolvedReturnType*/ undefined,
/*resolvedTypePredicate*/ undefined,
minArgCount,
(left.flags | right.flags) & SignatureFlags.PropagatingFlags,
flags,
);
result.compositeKind = TypeFlags.Intersection;
result.compositeSignatures = concatenate(left.compositeKind === TypeFlags.Intersection && left.compositeSignatures || [left], [right]);

View File

@ -0,0 +1,29 @@
signatureCombiningRestParameters1.ts(17,6): error TS2345: Argument of type 'any' is not assignable to parameter of type 'never'.
==== signatureCombiningRestParameters1.ts (1 errors) ====
// https://github.com/microsoft/TypeScript/issues/58371
type T1 = "A" | "B";
type T2 = {
C: [string];
D: [number];
};
declare const map: {
[K in T1 | keyof T2]: (...args: K extends keyof T2 ? T2[K] : []) => unknown;
};
declare const args: any;
for (const [key, fn] of Object.entries(map)) {
fn(...args);
~~~~~~~
!!! error TS2345: Argument of type 'any' is not assignable to parameter of type 'never'.
}
const test2: ((a: number, ...args: []) => void) &
((b: string) => void) &
((c: boolean) => void) = (arg) => {};

View File

@ -0,0 +1,62 @@
//// [tests/cases/compiler/signatureCombiningRestParameters1.ts] ////
=== signatureCombiningRestParameters1.ts ===
// https://github.com/microsoft/TypeScript/issues/58371
type T1 = "A" | "B";
>T1 : Symbol(T1, Decl(signatureCombiningRestParameters1.ts, 0, 0))
type T2 = {
>T2 : Symbol(T2, Decl(signatureCombiningRestParameters1.ts, 2, 20))
C: [string];
>C : Symbol(C, Decl(signatureCombiningRestParameters1.ts, 4, 11))
D: [number];
>D : Symbol(D, Decl(signatureCombiningRestParameters1.ts, 5, 14))
};
declare const map: {
>map : Symbol(map, Decl(signatureCombiningRestParameters1.ts, 9, 13))
[K in T1 | keyof T2]: (...args: K extends keyof T2 ? T2[K] : []) => unknown;
>K : Symbol(K, Decl(signatureCombiningRestParameters1.ts, 10, 3))
>T1 : Symbol(T1, Decl(signatureCombiningRestParameters1.ts, 0, 0))
>T2 : Symbol(T2, Decl(signatureCombiningRestParameters1.ts, 2, 20))
>args : Symbol(args, Decl(signatureCombiningRestParameters1.ts, 10, 25))
>K : Symbol(K, Decl(signatureCombiningRestParameters1.ts, 10, 3))
>T2 : Symbol(T2, Decl(signatureCombiningRestParameters1.ts, 2, 20))
>T2 : Symbol(T2, Decl(signatureCombiningRestParameters1.ts, 2, 20))
>K : Symbol(K, Decl(signatureCombiningRestParameters1.ts, 10, 3))
};
declare const args: any;
>args : Symbol(args, Decl(signatureCombiningRestParameters1.ts, 13, 13))
for (const [key, fn] of Object.entries(map)) {
>key : Symbol(key, Decl(signatureCombiningRestParameters1.ts, 15, 12))
>fn : Symbol(fn, Decl(signatureCombiningRestParameters1.ts, 15, 16))
>Object.entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>map : Symbol(map, Decl(signatureCombiningRestParameters1.ts, 9, 13))
fn(...args);
>fn : Symbol(fn, Decl(signatureCombiningRestParameters1.ts, 15, 16))
>args : Symbol(args, Decl(signatureCombiningRestParameters1.ts, 13, 13))
}
const test2: ((a: number, ...args: []) => void) &
>test2 : Symbol(test2, Decl(signatureCombiningRestParameters1.ts, 19, 5))
>a : Symbol(a, Decl(signatureCombiningRestParameters1.ts, 19, 15))
>args : Symbol(args, Decl(signatureCombiningRestParameters1.ts, 19, 25))
((b: string) => void) &
>b : Symbol(b, Decl(signatureCombiningRestParameters1.ts, 20, 4))
((c: boolean) => void) = (arg) => {};
>c : Symbol(c, Decl(signatureCombiningRestParameters1.ts, 21, 4))
>arg : Symbol(arg, Decl(signatureCombiningRestParameters1.ts, 21, 28))

View File

@ -0,0 +1,84 @@
//// [tests/cases/compiler/signatureCombiningRestParameters1.ts] ////
=== signatureCombiningRestParameters1.ts ===
// https://github.com/microsoft/TypeScript/issues/58371
type T1 = "A" | "B";
>T1 : T1
> : ^^
type T2 = {
>T2 : T2
> : ^^
C: [string];
>C : [string]
> : ^^^^^^^^
D: [number];
>D : [number]
> : ^^^^^^^^
};
declare const map: {
>map : { A: () => unknown; B: () => unknown; C: (args_0: string) => unknown; D: (args_0: number) => unknown; }
> : ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
[K in T1 | keyof T2]: (...args: K extends keyof T2 ? T2[K] : []) => unknown;
>args : K extends keyof T2 ? T2[K] : []
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
};
declare const args: any;
>args : any
> : ^^^
for (const [key, fn] of Object.entries(map)) {
>key : string
> : ^^^^^^
>fn : (() => unknown) | (() => unknown) | ((args_0: string) => unknown) | ((args_0: number) => unknown)
> : ^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>Object.entries(map) : [string, (() => unknown) | (() => unknown) | ((args_0: string) => unknown) | ((args_0: number) => unknown)][]
> : ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^
>Object.entries : { <T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][]; (o: {}): [string, any][]; }
> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^
>Object : ObjectConstructor
> : ^^^^^^^^^^^^^^^^^
>entries : { <T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][]; (o: {}): [string, any][]; }
> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^
>map : { A: () => unknown; B: () => unknown; C: (args_0: string) => unknown; D: (args_0: number) => unknown; }
> : ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
fn(...args);
>fn(...args) : unknown
> : ^^^^^^^
>fn : (() => unknown) | (() => unknown) | ((args_0: string) => unknown) | ((args_0: number) => unknown)
> : ^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>...args : any
> : ^^^
>args : any
> : ^^^
}
const test2: ((a: number, ...args: []) => void) &
>test2 : ((a: number) => void) & ((b: string) => void) & ((c: boolean) => void)
> : ^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^
>a : number
> : ^^^^^^
>args : []
> : ^^
((b: string) => void) &
>b : string
> : ^^^^^^
((c: boolean) => void) = (arg) => {};
>c : boolean
> : ^^^^^^^
>(arg) => {} : (arg: string | number | boolean) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number | boolean
> : ^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -0,0 +1,35 @@
//// [tests/cases/compiler/signatureCombiningRestParameters2.ts] ////
=== signatureCombiningRestParameters2.ts ===
interface Console {
>Console : Symbol(Console, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 0))
log(message?: any, ...optionalParams: any[]): void;
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 19))
>message : Symbol(message, Decl(signatureCombiningRestParameters2.ts, 1, 6))
>optionalParams : Symbol(optionalParams, Decl(signatureCombiningRestParameters2.ts, 1, 20))
}
let logs: string[] = [];
>logs : Symbol(logs, Decl(signatureCombiningRestParameters2.ts, 4, 3))
let originalLog: typeof console.log;
>originalLog : Symbol(originalLog, Decl(signatureCombiningRestParameters2.ts, 5, 3))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 19))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 19))
console.log = (...args) => {
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 19))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --), Decl(signatureCombiningRestParameters2.ts, 0, 19))
>args : Symbol(args, Decl(signatureCombiningRestParameters2.ts, 6, 15))
logs.push(...args);
>logs.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>logs : Symbol(logs, Decl(signatureCombiningRestParameters2.ts, 4, 3))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>args : Symbol(args, Decl(signatureCombiningRestParameters2.ts, 6, 15))
};

View File

@ -0,0 +1,57 @@
//// [tests/cases/compiler/signatureCombiningRestParameters2.ts] ////
=== signatureCombiningRestParameters2.ts ===
interface Console {
log(message?: any, ...optionalParams: any[]): void;
>log : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
>message : any
>optionalParams : any[]
> : ^^^^^
}
let logs: string[] = [];
>logs : string[]
> : ^^^^^^^^
>[] : never[]
> : ^^^^^^^
let originalLog: typeof console.log;
>originalLog : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
>console.log : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
>console : Console
> : ^^^^^^^
>log : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
console.log = (...args) => {
>console.log = (...args) => { logs.push(...args);} : (args_0?: any, ...args: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>console.log : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
>console : Console
> : ^^^^^^^
>log : { (...data: any[]): void; (message?: any, ...optionalParams: any[]): void; }
> : ^^^^^^ ^^ ^^^ ^^^ ^^^ ^^^^^ ^^ ^^^ ^^^
>(...args) => { logs.push(...args);} : (args_0?: any, ...args: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : [any?, ...any[]]
> : ^^^^^^^^^^^^^^^^
logs.push(...args);
>logs.push(...args) : number
> : ^^^^^^
>logs.push : (...items: string[]) => number
> : ^^^^ ^^^^^^^^^^^^^^^
>logs : string[]
> : ^^^^^^^^
>push : (...items: string[]) => number
> : ^^^^ ^^^^^^^^^^^^^^^
>...args : any
>args : [any?, ...any[]]
> : ^^^^^^^^^^^^^^^^
};

View File

@ -0,0 +1,93 @@
signatureCombiningRestParameters3.ts(81,20): error TS2345: Argument of type 'Mark<any>' is not assignable to parameter of type 'Mark<any> & Node<any>'.
Type 'Mark<any>' is missing the following properties from type 'Node<any>': type, name, parent, child
==== signatureCombiningRestParameters3.ts (1 errors) ====
interface ExtensionConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
declare class Extension<Options = any> {
type: string;
name: string;
parent: Extension | null;
child: Extension | null;
options: Options;
config: ExtensionConfig;
}
declare class Node<Options = any> {
type: string;
name: string;
parent: Node | null;
child: Node | null;
options: Options;
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Node,
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
options: Options;
config: MarkConfig;
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
type AnyConfig = ExtensionConfig | NodeConfig | MarkConfig;
type AnyExtension = Extension | Node | Mark;
declare const e: AnyExtension;
type RemoveThis<T> = T extends (...args: any) => any
? (...args: Parameters<T>) => ReturnType<T>
: T;
declare function getExtensionField<T = any>(
extension: AnyExtension,
field: string,
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
e,
"extendMarkSchema",
);
declare const extension: Mark<any>;
if (extendMarkSchema) {
extendMarkSchema(extension); // error
~~~~~~~~~
!!! error TS2345: Argument of type 'Mark<any>' is not assignable to parameter of type 'Mark<any> & Node<any>'.
!!! error TS2345: Type 'Mark<any>' is missing the following properties from type 'Node<any>': type, name, parent, child
}
export {};

View File

@ -0,0 +1,225 @@
//// [tests/cases/compiler/signatureCombiningRestParameters3.ts] ////
=== signatureCombiningRestParameters3.ts ===
interface ExtensionConfig<Options = any> {
>ExtensionConfig : Symbol(ExtensionConfig, Decl(signatureCombiningRestParameters3.ts, 0, 0))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 0, 26))
extendMarkSchema?:
>extendMarkSchema : Symbol(ExtensionConfig.extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 0, 42))
| ((
this: {
>this : Symbol(this, Decl(signatureCombiningRestParameters3.ts, 2, 8))
name: string;
>name : Symbol(name, Decl(signatureCombiningRestParameters3.ts, 3, 15))
options: Options;
>options : Symbol(options, Decl(signatureCombiningRestParameters3.ts, 4, 23))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 0, 26))
},
extension: Mark,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 6, 10))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters3.ts, 39, 1))
) => Record<string, any>)
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
| null;
}
declare class Extension<Options = any> {
>Extension : Symbol(Extension, Decl(signatureCombiningRestParameters3.ts, 10, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 12, 24))
type: string;
>type : Symbol(Extension.type, Decl(signatureCombiningRestParameters3.ts, 12, 40))
name: string;
>name : Symbol(Extension.name, Decl(signatureCombiningRestParameters3.ts, 13, 15))
parent: Extension | null;
>parent : Symbol(Extension.parent, Decl(signatureCombiningRestParameters3.ts, 14, 15))
>Extension : Symbol(Extension, Decl(signatureCombiningRestParameters3.ts, 10, 1))
child: Extension | null;
>child : Symbol(Extension.child, Decl(signatureCombiningRestParameters3.ts, 15, 27))
>Extension : Symbol(Extension, Decl(signatureCombiningRestParameters3.ts, 10, 1))
options: Options;
>options : Symbol(Extension.options, Decl(signatureCombiningRestParameters3.ts, 16, 26))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 12, 24))
config: ExtensionConfig;
>config : Symbol(Extension.config, Decl(signatureCombiningRestParameters3.ts, 17, 19))
>ExtensionConfig : Symbol(ExtensionConfig, Decl(signatureCombiningRestParameters3.ts, 0, 0))
}
declare class Node<Options = any> {
>Node : Symbol(Node, Decl(signatureCombiningRestParameters3.ts, 19, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 21, 19))
type: string;
>type : Symbol(Node.type, Decl(signatureCombiningRestParameters3.ts, 21, 35))
name: string;
>name : Symbol(Node.name, Decl(signatureCombiningRestParameters3.ts, 22, 15))
parent: Node | null;
>parent : Symbol(Node.parent, Decl(signatureCombiningRestParameters3.ts, 23, 15))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters3.ts, 19, 1))
child: Node | null;
>child : Symbol(Node.child, Decl(signatureCombiningRestParameters3.ts, 24, 22))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters3.ts, 19, 1))
options: Options;
>options : Symbol(Node.options, Decl(signatureCombiningRestParameters3.ts, 25, 21))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 21, 19))
}
interface NodeConfig<Options = any> {
>NodeConfig : Symbol(NodeConfig, Decl(signatureCombiningRestParameters3.ts, 27, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 29, 21))
extendMarkSchema?:
>extendMarkSchema : Symbol(NodeConfig.extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 29, 37))
| ((
this: {
>this : Symbol(this, Decl(signatureCombiningRestParameters3.ts, 31, 8))
name: string;
>name : Symbol(name, Decl(signatureCombiningRestParameters3.ts, 32, 15))
options: Options;
>options : Symbol(options, Decl(signatureCombiningRestParameters3.ts, 33, 23))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 29, 21))
},
extension: Node,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 35, 10))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters3.ts, 19, 1))
) => Record<string, any>)
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
| null;
}
declare class Mark<Options = any> {
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters3.ts, 39, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 41, 19))
options: Options;
>options : Symbol(Mark.options, Decl(signatureCombiningRestParameters3.ts, 41, 35))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 41, 19))
config: MarkConfig;
>config : Symbol(Mark.config, Decl(signatureCombiningRestParameters3.ts, 42, 19))
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters3.ts, 44, 1))
}
interface MarkConfig<Options = any> {
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters3.ts, 44, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 46, 21))
extendMarkSchema?:
>extendMarkSchema : Symbol(MarkConfig.extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 46, 37))
| ((
this: {
>this : Symbol(this, Decl(signatureCombiningRestParameters3.ts, 48, 8))
name: string;
>name : Symbol(name, Decl(signatureCombiningRestParameters3.ts, 49, 15))
options: Options;
>options : Symbol(options, Decl(signatureCombiningRestParameters3.ts, 50, 23))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters3.ts, 46, 21))
},
extension: Mark,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 52, 10))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters3.ts, 39, 1))
) => Record<string, any>)
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
| null;
}
type AnyConfig = ExtensionConfig | NodeConfig | MarkConfig;
>AnyConfig : Symbol(AnyConfig, Decl(signatureCombiningRestParameters3.ts, 56, 1))
>ExtensionConfig : Symbol(ExtensionConfig, Decl(signatureCombiningRestParameters3.ts, 0, 0))
>NodeConfig : Symbol(NodeConfig, Decl(signatureCombiningRestParameters3.ts, 27, 1))
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters3.ts, 44, 1))
type AnyExtension = Extension | Node | Mark;
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters3.ts, 58, 59))
>Extension : Symbol(Extension, Decl(signatureCombiningRestParameters3.ts, 10, 1))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters3.ts, 19, 1))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters3.ts, 39, 1))
declare const e: AnyExtension;
>e : Symbol(e, Decl(signatureCombiningRestParameters3.ts, 61, 13))
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters3.ts, 58, 59))
type RemoveThis<T> = T extends (...args: any) => any
>RemoveThis : Symbol(RemoveThis, Decl(signatureCombiningRestParameters3.ts, 61, 30))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 63, 16))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 63, 16))
>args : Symbol(args, Decl(signatureCombiningRestParameters3.ts, 63, 32))
? (...args: Parameters<T>) => ReturnType<T>
>args : Symbol(args, Decl(signatureCombiningRestParameters3.ts, 64, 5))
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 63, 16))
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 63, 16))
: T;
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 63, 16))
declare function getExtensionField<T = any>(
>getExtensionField : Symbol(getExtensionField, Decl(signatureCombiningRestParameters3.ts, 65, 6))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 67, 35))
extension: AnyExtension,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 67, 44))
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters3.ts, 58, 59))
field: string,
>field : Symbol(field, Decl(signatureCombiningRestParameters3.ts, 68, 26))
): RemoveThis<T>;
>RemoveThis : Symbol(RemoveThis, Decl(signatureCombiningRestParameters3.ts, 61, 30))
>T : Symbol(T, Decl(signatureCombiningRestParameters3.ts, 67, 35))
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 72, 5))
>getExtensionField : Symbol(getExtensionField, Decl(signatureCombiningRestParameters3.ts, 65, 6))
>AnyConfig : Symbol(AnyConfig, Decl(signatureCombiningRestParameters3.ts, 56, 1))
e,
>e : Symbol(e, Decl(signatureCombiningRestParameters3.ts, 61, 13))
"extendMarkSchema",
);
declare const extension: Mark<any>;
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 77, 13))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters3.ts, 39, 1))
if (extendMarkSchema) {
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 72, 5))
extendMarkSchema(extension); // error
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters3.ts, 72, 5))
>extension : Symbol(extension, Decl(signatureCombiningRestParameters3.ts, 77, 13))
}
export {};

View File

@ -0,0 +1,226 @@
//// [tests/cases/compiler/signatureCombiningRestParameters3.ts] ////
=== signatureCombiningRestParameters3.ts ===
interface ExtensionConfig<Options = any> {
extendMarkSchema?:
>extendMarkSchema : ((this: { name: string; options: Options; }, extension: Mark) => Record<string, any>) | null | undefined
> : ^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^
| ((
this: {
>this : { name: string; options: Options; }
> : ^^^^^^^^ ^^^^^^^^^^^ ^^^
name: string;
>name : string
> : ^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
},
extension: Mark,
>extension : Mark<any>
> : ^^^^^^^^^
) => Record<string, any>)
| null;
}
declare class Extension<Options = any> {
>Extension : Extension<Options>
> : ^^^^^^^^^^^^^^^^^^
type: string;
>type : string
> : ^^^^^^
name: string;
>name : string
> : ^^^^^^
parent: Extension | null;
>parent : Extension<any> | null
> : ^^^^^^^^^^^^^^^^^^^^^
child: Extension | null;
>child : Extension<any> | null
> : ^^^^^^^^^^^^^^^^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
config: ExtensionConfig;
>config : ExtensionConfig<any>
> : ^^^^^^^^^^^^^^^^^^^^
}
declare class Node<Options = any> {
>Node : Node<Options>
> : ^^^^^^^^^^^^^
type: string;
>type : string
> : ^^^^^^
name: string;
>name : string
> : ^^^^^^
parent: Node | null;
>parent : Node<any> | null
> : ^^^^^^^^^^^^^^^^
child: Node | null;
>child : Node<any> | null
> : ^^^^^^^^^^^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
>extendMarkSchema : ((this: { name: string; options: Options; }, extension: Node) => Record<string, any>) | null | undefined
> : ^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^
| ((
this: {
>this : { name: string; options: Options; }
> : ^^^^^^^^ ^^^^^^^^^^^ ^^^
name: string;
>name : string
> : ^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
},
extension: Node,
>extension : Node<any>
> : ^^^^^^^^^
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
>Mark : Mark<Options>
> : ^^^^^^^^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
config: MarkConfig;
>config : MarkConfig<any>
> : ^^^^^^^^^^^^^^^
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
>extendMarkSchema : ((this: { name: string; options: Options; }, extension: Mark) => Record<string, any>) | null | undefined
> : ^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^
| ((
this: {
>this : { name: string; options: Options; }
> : ^^^^^^^^ ^^^^^^^^^^^ ^^^
name: string;
>name : string
> : ^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
},
extension: Mark,
>extension : Mark<any>
> : ^^^^^^^^^
) => Record<string, any>)
| null;
}
type AnyConfig = ExtensionConfig | NodeConfig | MarkConfig;
>AnyConfig : AnyConfig
> : ^^^^^^^^^
type AnyExtension = Extension | Node | Mark;
>AnyExtension : AnyExtension
> : ^^^^^^^^^^^^
declare const e: AnyExtension;
>e : AnyExtension
> : ^^^^^^^^^^^^
type RemoveThis<T> = T extends (...args: any) => any
>RemoveThis : RemoveThis<T>
> : ^^^^^^^^^^^^^
>args : any
> : ^^^
? (...args: Parameters<T>) => ReturnType<T>
>args : Parameters<T>
> : ^^^^^^^^^^^^^
: T;
declare function getExtensionField<T = any>(
>getExtensionField : <T = any>(extension: AnyExtension, field: string) => RemoveThis<T>
> : ^ ^^^^^^^^ ^^ ^^ ^^ ^^^^^
extension: AnyExtension,
>extension : AnyExtension
> : ^^^^^^^^^^^^
field: string,
>field : string
> : ^^^^^^
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
>extendMarkSchema : ((extension: Mark<any>) => Record<string, any>) | ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>getExtensionField<AnyConfig["extendMarkSchema"]>( e, "extendMarkSchema",) : ((extension: Mark<any>) => Record<string, any>) | ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>getExtensionField : <T = any>(extension: AnyExtension, field: string) => RemoveThis<T>
> : ^ ^^^^^^^^ ^^ ^^ ^^ ^^^^^
e,
>e : AnyExtension
> : ^^^^^^^^^^^^
"extendMarkSchema",
>"extendMarkSchema" : "extendMarkSchema"
> : ^^^^^^^^^^^^^^^^^^
);
declare const extension: Mark<any>;
>extension : Mark<any>
> : ^^^^^^^^^
if (extendMarkSchema) {
>extendMarkSchema : ((extension: Mark<any>) => Record<string, any>) | ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
extendMarkSchema(extension); // error
>extendMarkSchema(extension) : Record<string, any>
> : ^^^^^^^^^^^^^^^^^^^
>extendMarkSchema : ((extension: Mark<any>) => Record<string, any>) | ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>extension : Mark<any>
> : ^^^^^^^^^
}
export {};

View File

@ -0,0 +1,72 @@
signatureCombiningRestParameters4.ts(60,20): error TS2345: Argument of type 'Mark<any>' is not assignable to parameter of type 'Node<any> & Mark<any>'.
Type 'Mark<any>' is missing the following properties from type 'Node<any>': type, name, parent, child
==== signatureCombiningRestParameters4.ts (1 errors) ====
declare class Node<Options = any> {
type: string;
name: string;
parent: Node | null;
child: Node | null;
options: Options;
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Node,
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
options: Options;
config: MarkConfig;
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
type AnyConfig = NodeConfig | MarkConfig;
type AnyExtension = Node | Mark;
declare const e: AnyExtension;
type RemoveThis<T> = T extends (...args: any) => any
? (...args: Parameters<T>) => ReturnType<T>
: T;
declare function getExtensionField<T = any>(
extension: AnyExtension,
field: string,
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
e,
"extendMarkSchema",
);
declare const extension: Mark<any>;
if (extendMarkSchema) {
extendMarkSchema(extension); // error
~~~~~~~~~
!!! error TS2345: Argument of type 'Mark<any>' is not assignable to parameter of type 'Node<any> & Mark<any>'.
!!! error TS2345: Type 'Mark<any>' is missing the following properties from type 'Node<any>': type, name, parent, child
}
export {};

View File

@ -0,0 +1,167 @@
//// [tests/cases/compiler/signatureCombiningRestParameters4.ts] ////
=== signatureCombiningRestParameters4.ts ===
declare class Node<Options = any> {
>Node : Symbol(Node, Decl(signatureCombiningRestParameters4.ts, 0, 0))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 0, 19))
type: string;
>type : Symbol(Node.type, Decl(signatureCombiningRestParameters4.ts, 0, 35))
name: string;
>name : Symbol(Node.name, Decl(signatureCombiningRestParameters4.ts, 1, 15))
parent: Node | null;
>parent : Symbol(Node.parent, Decl(signatureCombiningRestParameters4.ts, 2, 15))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters4.ts, 0, 0))
child: Node | null;
>child : Symbol(Node.child, Decl(signatureCombiningRestParameters4.ts, 3, 22))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters4.ts, 0, 0))
options: Options;
>options : Symbol(Node.options, Decl(signatureCombiningRestParameters4.ts, 4, 21))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 0, 19))
}
interface NodeConfig<Options = any> {
>NodeConfig : Symbol(NodeConfig, Decl(signatureCombiningRestParameters4.ts, 6, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 8, 21))
extendMarkSchema?:
>extendMarkSchema : Symbol(NodeConfig.extendMarkSchema, Decl(signatureCombiningRestParameters4.ts, 8, 37))
| ((
this: {
>this : Symbol(this, Decl(signatureCombiningRestParameters4.ts, 10, 8))
name: string;
>name : Symbol(name, Decl(signatureCombiningRestParameters4.ts, 11, 15))
options: Options;
>options : Symbol(options, Decl(signatureCombiningRestParameters4.ts, 12, 23))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 8, 21))
},
extension: Node,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters4.ts, 14, 10))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters4.ts, 0, 0))
) => Record<string, any>)
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
| null;
}
declare class Mark<Options = any> {
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters4.ts, 18, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 20, 19))
options: Options;
>options : Symbol(Mark.options, Decl(signatureCombiningRestParameters4.ts, 20, 35))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 20, 19))
config: MarkConfig;
>config : Symbol(Mark.config, Decl(signatureCombiningRestParameters4.ts, 21, 19))
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters4.ts, 23, 1))
}
interface MarkConfig<Options = any> {
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters4.ts, 23, 1))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 25, 21))
extendMarkSchema?:
>extendMarkSchema : Symbol(MarkConfig.extendMarkSchema, Decl(signatureCombiningRestParameters4.ts, 25, 37))
| ((
this: {
>this : Symbol(this, Decl(signatureCombiningRestParameters4.ts, 27, 8))
name: string;
>name : Symbol(name, Decl(signatureCombiningRestParameters4.ts, 28, 15))
options: Options;
>options : Symbol(options, Decl(signatureCombiningRestParameters4.ts, 29, 23))
>Options : Symbol(Options, Decl(signatureCombiningRestParameters4.ts, 25, 21))
},
extension: Mark,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters4.ts, 31, 10))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters4.ts, 18, 1))
) => Record<string, any>)
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
| null;
}
type AnyConfig = NodeConfig | MarkConfig;
>AnyConfig : Symbol(AnyConfig, Decl(signatureCombiningRestParameters4.ts, 35, 1))
>NodeConfig : Symbol(NodeConfig, Decl(signatureCombiningRestParameters4.ts, 6, 1))
>MarkConfig : Symbol(MarkConfig, Decl(signatureCombiningRestParameters4.ts, 23, 1))
type AnyExtension = Node | Mark;
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters4.ts, 37, 41))
>Node : Symbol(Node, Decl(signatureCombiningRestParameters4.ts, 0, 0))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters4.ts, 18, 1))
declare const e: AnyExtension;
>e : Symbol(e, Decl(signatureCombiningRestParameters4.ts, 40, 13))
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters4.ts, 37, 41))
type RemoveThis<T> = T extends (...args: any) => any
>RemoveThis : Symbol(RemoveThis, Decl(signatureCombiningRestParameters4.ts, 40, 30))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 42, 16))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 42, 16))
>args : Symbol(args, Decl(signatureCombiningRestParameters4.ts, 42, 32))
? (...args: Parameters<T>) => ReturnType<T>
>args : Symbol(args, Decl(signatureCombiningRestParameters4.ts, 43, 5))
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 42, 16))
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 42, 16))
: T;
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 42, 16))
declare function getExtensionField<T = any>(
>getExtensionField : Symbol(getExtensionField, Decl(signatureCombiningRestParameters4.ts, 44, 6))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 46, 35))
extension: AnyExtension,
>extension : Symbol(extension, Decl(signatureCombiningRestParameters4.ts, 46, 44))
>AnyExtension : Symbol(AnyExtension, Decl(signatureCombiningRestParameters4.ts, 37, 41))
field: string,
>field : Symbol(field, Decl(signatureCombiningRestParameters4.ts, 47, 26))
): RemoveThis<T>;
>RemoveThis : Symbol(RemoveThis, Decl(signatureCombiningRestParameters4.ts, 40, 30))
>T : Symbol(T, Decl(signatureCombiningRestParameters4.ts, 46, 35))
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters4.ts, 51, 5))
>getExtensionField : Symbol(getExtensionField, Decl(signatureCombiningRestParameters4.ts, 44, 6))
>AnyConfig : Symbol(AnyConfig, Decl(signatureCombiningRestParameters4.ts, 35, 1))
e,
>e : Symbol(e, Decl(signatureCombiningRestParameters4.ts, 40, 13))
"extendMarkSchema",
);
declare const extension: Mark<any>;
>extension : Symbol(extension, Decl(signatureCombiningRestParameters4.ts, 56, 13))
>Mark : Symbol(Mark, Decl(signatureCombiningRestParameters4.ts, 18, 1))
if (extendMarkSchema) {
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters4.ts, 51, 5))
extendMarkSchema(extension); // error
>extendMarkSchema : Symbol(extendMarkSchema, Decl(signatureCombiningRestParameters4.ts, 51, 5))
>extension : Symbol(extension, Decl(signatureCombiningRestParameters4.ts, 56, 13))
}
export {};

View File

@ -0,0 +1,170 @@
//// [tests/cases/compiler/signatureCombiningRestParameters4.ts] ////
=== signatureCombiningRestParameters4.ts ===
declare class Node<Options = any> {
>Node : Node<Options>
> : ^^^^^^^^^^^^^
type: string;
>type : string
> : ^^^^^^
name: string;
>name : string
> : ^^^^^^
parent: Node | null;
>parent : Node<any> | null
> : ^^^^^^^^^^^^^^^^
child: Node | null;
>child : Node<any> | null
> : ^^^^^^^^^^^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
>extendMarkSchema : ((this: { name: string; options: Options; }, extension: Node) => Record<string, any>) | null | undefined
> : ^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^
| ((
this: {
>this : { name: string; options: Options; }
> : ^^^^^^^^ ^^^^^^^^^^^ ^^^
name: string;
>name : string
> : ^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
},
extension: Node,
>extension : Node<any>
> : ^^^^^^^^^
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
>Mark : Mark<Options>
> : ^^^^^^^^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
config: MarkConfig;
>config : MarkConfig<any>
> : ^^^^^^^^^^^^^^^
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
>extendMarkSchema : ((this: { name: string; options: Options; }, extension: Mark) => Record<string, any>) | null | undefined
> : ^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^
| ((
this: {
>this : { name: string; options: Options; }
> : ^^^^^^^^ ^^^^^^^^^^^ ^^^
name: string;
>name : string
> : ^^^^^^
options: Options;
>options : Options
> : ^^^^^^^
},
extension: Mark,
>extension : Mark<any>
> : ^^^^^^^^^
) => Record<string, any>)
| null;
}
type AnyConfig = NodeConfig | MarkConfig;
>AnyConfig : AnyConfig
> : ^^^^^^^^^
type AnyExtension = Node | Mark;
>AnyExtension : AnyExtension
> : ^^^^^^^^^^^^
declare const e: AnyExtension;
>e : AnyExtension
> : ^^^^^^^^^^^^
type RemoveThis<T> = T extends (...args: any) => any
>RemoveThis : RemoveThis<T>
> : ^^^^^^^^^^^^^
>args : any
> : ^^^
? (...args: Parameters<T>) => ReturnType<T>
>args : Parameters<T>
> : ^^^^^^^^^^^^^
: T;
declare function getExtensionField<T = any>(
>getExtensionField : <T = any>(extension: AnyExtension, field: string) => RemoveThis<T>
> : ^ ^^^^^^^^ ^^ ^^ ^^ ^^^^^
extension: AnyExtension,
>extension : AnyExtension
> : ^^^^^^^^^^^^
field: string,
>field : string
> : ^^^^^^
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
>extendMarkSchema : ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>getExtensionField<AnyConfig["extendMarkSchema"]>( e, "extendMarkSchema",) : ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>getExtensionField : <T = any>(extension: AnyExtension, field: string) => RemoveThis<T>
> : ^ ^^^^^^^^ ^^ ^^ ^^ ^^^^^
e,
>e : AnyExtension
> : ^^^^^^^^^^^^
"extendMarkSchema",
>"extendMarkSchema" : "extendMarkSchema"
> : ^^^^^^^^^^^^^^^^^^
);
declare const extension: Mark<any>;
>extension : Mark<any>
> : ^^^^^^^^^
if (extendMarkSchema) {
>extendMarkSchema : ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>) | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
extendMarkSchema(extension); // error
>extendMarkSchema(extension) : Record<string, any>
> : ^^^^^^^^^^^^^^^^^^^
>extendMarkSchema : ((extension: Node<any>) => Record<string, any>) | ((extension: Mark<any>) => Record<string, any>)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>extension : Mark<any>
> : ^^^^^^^^^
}
export {};

View File

@ -0,0 +1,34 @@
signatureCombiningRestParameters5.ts(6,11): error TS2345: Argument of type 'boolean[]' is not assignable to parameter of type 'boolean'.
signatureCombiningRestParameters5.ts(22,14): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'number'.
==== signatureCombiningRestParameters5.ts (2 errors) ====
declare const test1:
| ((...args: [a: string | number, b: number | boolean]) => void)
| ((...args: [c: number | boolean, d: string | boolean]) => void);
test1(42, true);
test1(42, [true]); // error
~~~~~~
!!! error TS2345: Argument of type 'boolean[]' is not assignable to parameter of type 'boolean'.
declare function test2<
A extends readonly unknown[],
B extends readonly unknown[],
>(
c: (...args: A) => void,
d: (...args: B) => void,
e: (arg: typeof c | typeof d) => void,
): void;
test2(
(a: number | boolean, b: string | number) => {},
(c: string | boolean, d: number | boolean) => {},
(cb) => {
cb(true, 42);
cb(true, [42]); // error
~~~~
!!! error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'number'.
},
);

View File

@ -0,0 +1,69 @@
//// [tests/cases/compiler/signatureCombiningRestParameters5.ts] ////
=== signatureCombiningRestParameters5.ts ===
declare const test1:
>test1 : Symbol(test1, Decl(signatureCombiningRestParameters5.ts, 0, 13))
| ((...args: [a: string | number, b: number | boolean]) => void)
>args : Symbol(args, Decl(signatureCombiningRestParameters5.ts, 1, 6))
| ((...args: [c: number | boolean, d: string | boolean]) => void);
>args : Symbol(args, Decl(signatureCombiningRestParameters5.ts, 2, 6))
test1(42, true);
>test1 : Symbol(test1, Decl(signatureCombiningRestParameters5.ts, 0, 13))
test1(42, [true]); // error
>test1 : Symbol(test1, Decl(signatureCombiningRestParameters5.ts, 0, 13))
declare function test2<
>test2 : Symbol(test2, Decl(signatureCombiningRestParameters5.ts, 5, 18))
A extends readonly unknown[],
>A : Symbol(A, Decl(signatureCombiningRestParameters5.ts, 7, 23))
B extends readonly unknown[],
>B : Symbol(B, Decl(signatureCombiningRestParameters5.ts, 8, 31))
>(
c: (...args: A) => void,
>c : Symbol(c, Decl(signatureCombiningRestParameters5.ts, 10, 2))
>args : Symbol(args, Decl(signatureCombiningRestParameters5.ts, 11, 6))
>A : Symbol(A, Decl(signatureCombiningRestParameters5.ts, 7, 23))
d: (...args: B) => void,
>d : Symbol(d, Decl(signatureCombiningRestParameters5.ts, 11, 26))
>args : Symbol(args, Decl(signatureCombiningRestParameters5.ts, 12, 6))
>B : Symbol(B, Decl(signatureCombiningRestParameters5.ts, 8, 31))
e: (arg: typeof c | typeof d) => void,
>e : Symbol(e, Decl(signatureCombiningRestParameters5.ts, 12, 26))
>arg : Symbol(arg, Decl(signatureCombiningRestParameters5.ts, 13, 6))
>c : Symbol(c, Decl(signatureCombiningRestParameters5.ts, 10, 2))
>d : Symbol(d, Decl(signatureCombiningRestParameters5.ts, 11, 26))
): void;
test2(
>test2 : Symbol(test2, Decl(signatureCombiningRestParameters5.ts, 5, 18))
(a: number | boolean, b: string | number) => {},
>a : Symbol(a, Decl(signatureCombiningRestParameters5.ts, 17, 3))
>b : Symbol(b, Decl(signatureCombiningRestParameters5.ts, 17, 23))
(c: string | boolean, d: number | boolean) => {},
>c : Symbol(c, Decl(signatureCombiningRestParameters5.ts, 18, 3))
>d : Symbol(d, Decl(signatureCombiningRestParameters5.ts, 18, 23))
(cb) => {
>cb : Symbol(cb, Decl(signatureCombiningRestParameters5.ts, 19, 3))
cb(true, 42);
>cb : Symbol(cb, Decl(signatureCombiningRestParameters5.ts, 19, 3))
cb(true, [42]); // error
>cb : Symbol(cb, Decl(signatureCombiningRestParameters5.ts, 19, 3))
},
);

View File

@ -0,0 +1,121 @@
//// [tests/cases/compiler/signatureCombiningRestParameters5.ts] ////
=== signatureCombiningRestParameters5.ts ===
declare const test1:
>test1 : ((a: string | number, b: number | boolean) => void) | ((c: number | boolean, d: string | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
| ((...args: [a: string | number, b: number | boolean]) => void)
>args : [a: string | number, b: number | boolean]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ((...args: [c: number | boolean, d: string | boolean]) => void);
>args : [c: number | boolean, d: string | boolean]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
test1(42, true);
>test1(42, true) : void
> : ^^^^
>test1 : ((a: string | number, b: number | boolean) => void) | ((c: number | boolean, d: string | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>42 : 42
> : ^^
>true : true
> : ^^^^
test1(42, [true]); // error
>test1(42, [true]) : void
> : ^^^^
>test1 : ((a: string | number, b: number | boolean) => void) | ((c: number | boolean, d: string | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>42 : 42
> : ^^
>[true] : boolean[]
> : ^^^^^^^^^
>true : true
> : ^^^^
declare function test2<
>test2 : <A extends readonly unknown[], B extends readonly unknown[]>(c: (...args: A) => void, d: (...args: B) => void, e: (arg: typeof c | typeof d) => void) => void
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
A extends readonly unknown[],
B extends readonly unknown[],
>(
c: (...args: A) => void,
>c : (...args: A) => void
> : ^^^^ ^^ ^^^^^
>args : A
> : ^
d: (...args: B) => void,
>d : (...args: B) => void
> : ^^^^ ^^ ^^^^^
>args : B
> : ^
e: (arg: typeof c | typeof d) => void,
>e : (arg: typeof c | typeof d) => void
> : ^ ^^ ^^^^^
>arg : ((...args: A) => void) | ((...args: B) => void)
> : ^^^^^ ^^ ^^^^^ ^^^^^^^^^ ^^ ^^^^^ ^
>c : (...args: A) => void
> : ^^^^ ^^ ^^^^^
>d : (...args: B) => void
> : ^^^^ ^^ ^^^^^
): void;
test2(
>test2( (a: number | boolean, b: string | number) => {}, (c: string | boolean, d: number | boolean) => {}, (cb) => { cb(true, 42); cb(true, [42]); // error },) : void
> : ^^^^
>test2 : <A extends readonly unknown[], B extends readonly unknown[]>(c: (...args: A) => void, d: (...args: B) => void, e: (arg: typeof c | typeof d) => void) => void
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
(a: number | boolean, b: string | number) => {},
>(a: number | boolean, b: string | number) => {} : (a: number | boolean, b: string | number) => void
> : ^ ^^ ^^ ^^ ^^^^^^^^^
>a : number | boolean
> : ^^^^^^^^^^^^^^^^
>b : string | number
> : ^^^^^^^^^^^^^^^
(c: string | boolean, d: number | boolean) => {},
>(c: string | boolean, d: number | boolean) => {} : (c: string | boolean, d: number | boolean) => void
> : ^ ^^ ^^ ^^ ^^^^^^^^^
>c : string | boolean
> : ^^^^^^^^^^^^^^^^
>d : number | boolean
> : ^^^^^^^^^^^^^^^^
(cb) => {
>(cb) => { cb(true, 42); cb(true, [42]); // error } : (cb: ((a: number | boolean, b: string | number) => void) | ((c: string | boolean, d: number | boolean) => void)) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^
>cb : ((a: number | boolean, b: string | number) => void) | ((c: string | boolean, d: number | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
cb(true, 42);
>cb(true, 42) : void
> : ^^^^
>cb : ((a: number | boolean, b: string | number) => void) | ((c: string | boolean, d: number | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>true : true
> : ^^^^
>42 : 42
> : ^^
cb(true, [42]); // error
>cb(true, [42]) : void
> : ^^^^
>cb : ((a: number | boolean, b: string | number) => void) | ((c: string | boolean, d: number | boolean) => void)
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
>true : true
> : ^^^^
>[42] : number[]
> : ^^^^^^^^
>42 : 42
> : ^^
},
);

View File

@ -0,0 +1,26 @@
// @strict: true
// @lib: esnext
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/58371
type T1 = "A" | "B";
type T2 = {
C: [string];
D: [number];
};
declare const map: {
[K in T1 | keyof T2]: (...args: K extends keyof T2 ? T2[K] : []) => unknown;
};
declare const args: any;
for (const [key, fn] of Object.entries(map)) {
fn(...args);
}
const test2: ((a: number, ...args: []) => void) &
((b: string) => void) &
((c: boolean) => void) = (arg) => {};

View File

@ -0,0 +1,13 @@
// @strict: true
// @lib: dom,esnext
// @noEmit: true
interface Console {
log(message?: any, ...optionalParams: any[]): void;
}
let logs: string[] = [];
let originalLog: typeof console.log;
console.log = (...args) => {
logs.push(...args);
};

View File

@ -0,0 +1,87 @@
// @strict: true
// @noEmit: true
interface ExtensionConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
declare class Extension<Options = any> {
type: string;
name: string;
parent: Extension | null;
child: Extension | null;
options: Options;
config: ExtensionConfig;
}
declare class Node<Options = any> {
type: string;
name: string;
parent: Node | null;
child: Node | null;
options: Options;
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Node,
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
options: Options;
config: MarkConfig;
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
type AnyConfig = ExtensionConfig | NodeConfig | MarkConfig;
type AnyExtension = Extension | Node | Mark;
declare const e: AnyExtension;
type RemoveThis<T> = T extends (...args: any) => any
? (...args: Parameters<T>) => ReturnType<T>
: T;
declare function getExtensionField<T = any>(
extension: AnyExtension,
field: string,
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
e,
"extendMarkSchema",
);
declare const extension: Mark<any>;
if (extendMarkSchema) {
extendMarkSchema(extension); // error
}
export {};

View File

@ -0,0 +1,66 @@
// @strict: true
// @noEmit: true
declare class Node<Options = any> {
type: string;
name: string;
parent: Node | null;
child: Node | null;
options: Options;
}
interface NodeConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Node,
) => Record<string, any>)
| null;
}
declare class Mark<Options = any> {
options: Options;
config: MarkConfig;
}
interface MarkConfig<Options = any> {
extendMarkSchema?:
| ((
this: {
name: string;
options: Options;
},
extension: Mark,
) => Record<string, any>)
| null;
}
type AnyConfig = NodeConfig | MarkConfig;
type AnyExtension = Node | Mark;
declare const e: AnyExtension;
type RemoveThis<T> = T extends (...args: any) => any
? (...args: Parameters<T>) => ReturnType<T>
: T;
declare function getExtensionField<T = any>(
extension: AnyExtension,
field: string,
): RemoveThis<T>;
const extendMarkSchema = getExtensionField<AnyConfig["extendMarkSchema"]>(
e,
"extendMarkSchema",
);
declare const extension: Mark<any>;
if (extendMarkSchema) {
extendMarkSchema(extension); // error
}
export {};

View File

@ -0,0 +1,27 @@
// @strict: true
// @noEmit: true
declare const test1:
| ((...args: [a: string | number, b: number | boolean]) => void)
| ((...args: [c: number | boolean, d: string | boolean]) => void);
test1(42, true);
test1(42, [true]); // error
declare function test2<
A extends readonly unknown[],
B extends readonly unknown[],
>(
c: (...args: A) => void,
d: (...args: B) => void,
e: (arg: typeof c | typeof d) => void,
): void;
test2(
(a: number | boolean, b: string | number) => {},
(c: string | boolean, d: number | boolean) => {},
(cb) => {
cb(true, 42);
cb(true, [42]); // error
},
);

View File

@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
// @strict: true
//// const optionals: ((a?: number) => unknown) & ((b?: string) => unknown) = (
//// arg,
//// ) =/**/> {};
verify.quickInfoAt(
"",
`function(arg: string | number | undefined): void`,
);