Skip to content

4.1.1-rc strange Type is not assignable to type never with yield & generators #41428

Closed
@eamodio

Description

@eamodio

TypeScript Version: 4.1.0-beta (4.1.1-rc too)

//cc @mjbvz

Expected behavior:
No error on the following line

const selection = yield step;

As it works fine in TypeScript 4.0.5, and I'm unsure where the never is even coming from. Here is the actual source if it is interesting: https://github.com/eamodio/vscode-gitlens/blob/787bc8f3a976135d51032547e209b93267e14b2f/src%2Fcommands%2FquickCommand.steps.ts#L1794-L1814

Actual behavior:
Error on the line

Type 'QuickPickStep<QuickPickItem>' is not assignable to type 'never'.(2322)

Related Issues:

Code

export enum Directive {
	Back,
	Cancel,
	LoadMore,
	Noop,
}

export namespace Directive {
	export function is<T>(value: Directive | T): value is Directive {
		return typeof value === 'number' && Directive[value] != null;
	}
}

export interface QuickPickItem {
	label: string;
	description?: string;
	detail?: string;
	picked?: boolean;
	alwaysShow?: boolean;
}


export interface QuickInputStep {

	placeholder?: string;
	prompt?: string;
	title?: string;
}

export interface QuickPickStep<T extends QuickPickItem = QuickPickItem> {
	placeholder?: string;
	title?: string;
}

export type StepGenerator =
	| Generator<QuickPickStep | QuickInputStep, StepResult<void | undefined>, any | undefined>
	| AsyncGenerator<QuickPickStep | QuickInputStep, StepResult<void | undefined>, any | undefined>;

export type StepItemType<T> = T extends QuickPickStep<infer U> ? U[] : T extends QuickInputStep ? string : never;
export namespace StepResult {
	export const Break = Symbol('BreakStep');
}
export type StepResult<T> = typeof StepResult.Break | T;
export type StepResultGenerator<T> =
	| Generator<QuickPickStep | QuickInputStep, StepResult<T>, any | undefined>
	| AsyncGenerator<QuickPickStep | QuickInputStep, StepResult<T>, any | undefined>;
export type StepSelection<T> = T extends QuickPickStep<infer U>
	? U[] | Directive
	: T extends QuickInputStep
	? string | Directive
	: never;
export type PartialStepState<T = unknown> = Partial<T> & { counter: number; confirm?: boolean; startingStep?: number };
export type StepState<T = Record<string, unknown>> = T & { counter: number; confirm?: boolean; startingStep?: number };

export function canPickStepContinue<T extends QuickPickStep>(
	_step: T,
	_state: PartialStepState,
	_selection: StepItemType<T> | Directive,
): _selection is StepItemType<T> {
	return false;
}

export function createPickStep<T extends QuickPickItem>(step: QuickPickStep<T>): QuickPickStep<T> {
	return step;
}

export function* showStep<
	State extends PartialStepState & { repo: any },
	Context extends { repos: any[]; title: string; status: any }
>(state: State, _context: Context): StepResultGenerator<QuickPickItem> {
	const step: QuickPickStep<QuickPickItem> = createPickStep<QuickPickItem>({
		title: '',
		placeholder: ''
	});
	const selection: StepSelection<typeof step> = yield step;
	return canPickStepContinue(step, state, selection) ? selection[0] : StepResult.Break;
}
Output
export var Directive;
(function (Directive) {
    Directive[Directive["Back"] = 0] = "Back";
    Directive[Directive["Cancel"] = 1] = "Cancel";
    Directive[Directive["LoadMore"] = 2] = "LoadMore";
    Directive[Directive["Noop"] = 3] = "Noop";
})(Directive || (Directive = {}));
(function (Directive) {
    function is(value) {
        return typeof value === 'number' && Directive[value] != null;
    }
    Directive.is = is;
})(Directive || (Directive = {}));
export var StepResult;
(function (StepResult) {
    StepResult.Break = Symbol('BreakStep');
})(StepResult || (StepResult = {}));
export function canPickStepContinue(_step, _state, _selection) {
    return false;
}
export function createPickStep(step) {
    return step;
}
export function* showStep(state, _context) {
    const step = createPickStep({
        title: '',
        placeholder: ''
    });
    const selection = yield step;
    return canPickStepContinue(step, state, selection) ? selection[0] : StepResult.Break;
}
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2019",
    "module": "ESNext"
  }
}

Playground Link: Provided

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions