Skip to content

Inferred type of generic parameter wrong in complex case involving mapped types #33568

Closed
@aslatter

Description

@aslatter

TypeScript Version: 3.5.1 (also nightly, per playground)

Search Terms: mapped type interface generic parameter

Code

Sorry for the size of the repro. In TypeScript 3.3.3 this example-code type-checked without errors. As of (at least?) 3.5.1 and later I get the error:

function save(_response: IResponse<string>): void
Argument of type '(_response: IResponse<string>) => void' is not assignable to parameter of type 'IExportCallback<unknown>'.
  Types of parameters '_response' and 'response' are incompatible.
    Type 'IResponse<unknown>' is not assignable to type 'IResponse<string>'.
      Type 'unknown' is not assignable to type 'string'.
export function save(_response: IRootResponse<string>): void {}

exportCommand(save);

declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;

interface IExportCallback<TResponse> {
	(response: IRootResponse<TResponse>): void;
}

type IRootResponse<TResponse> =
	TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;

interface IRecord {
	readonly Id: string;
}

declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
	sendRecord(): void;
};

declare type IResponse<T> = {
	sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
};

/**
 * Get the list of property names on type T that are of a given type
 */
declare type GetPropertyNamesOfType<T, RestrictToType> = {
	[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
}[Extract<keyof T, string>];
/**
 * Get all the properties on type T that are of a given type
 */
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
	T,
	GetPropertyNamesOfType<Required<T>, RestrictToType>
>;

Expected behavior:

The example program to type-check.

Actual behavior:

Example program does not type-check.

We can work-around this by supplying type-parameters to the invocation of exportCommand, however the (non-simplified) version of this bug comes up multiple times in our code-base, and it would be nice to infer the type-parameters from the passed-in callback (like we could prior to v3.5).

For the work-around, change the invocation of exportCommand exportCommand<string>(save); (from exportCommand(save);).

Playground Link:

Related Issues:

The auto-issue searcher thing in GitHub found issues that sounded similar but are listed as affecting versions prior to 3.3 (where this code worked):

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions