Microsoft/TypeScript

Narrowing `this` using custom type predicate affected by TS 5.0

Open

#53,436 创建于 2023年3月22日

在 GitHub 查看
 (5 评论) (1 反应) (0 负责人)TypeScript (6,726 fork)batch import
BugDomain: This-TypingHelp Wanted

仓库指标

Star
 (48,455 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 9 个 PR)

描述

Bug Report

🔎 Search Terms

narrowing this predicate

🕗 Version & Regression Information

  • This changed between versions 4.9 and 5.0

⏯ Playground Link

Playground link with relevant code

💻 Code

interface Typestate<TContext extends object> {
  value: string;
  context: TContext;
}

interface State<TContext extends object, TState extends Typestate<TContext>> {
  value: TState["value"];
  context: TContext;
  matches: <TSV extends TState["value"]>(
    value: TSV
  ) => this is TState extends {
    value: TSV;
  }
    ? TState & {
        value: TSV;
      }
    : never;
}

interface Machine<TContext extends object, TState extends Typestate<TContext>> {
  initialState: State<TContext, TState>;
}

export declare function createMachine<
  TContext extends object,
  TState extends Typestate<TContext> = {
    value: any;
    context: TContext;
  }
>(): Machine<TContext, TState>;

const machine = createMachine<{ count: number }>();
const state = machine.initialState;

if (state.matches("idle")) {
  ((_accept: number) => {})(state.context.count);
  // @ts-expect-error
  ((_accept: string) => {})(state.context.count);
} else if (state.matches("latest")) {
  ((_accept: number) => {})(state.context.count);
  // @ts-expect-error
  ((_accept: string) => {})(state.context.count);
}

🙁 Actual behavior

state gets narrowed down to never in the else branch

🙂 Expected behavior

state to only get narrowed down to the appropriate value within the if branch

cc @ahejlsberg

贡献者指南