Skip to content

Type narrowing on template literal types #46045

Closed
@martinfrancois

Description

@martinfrancois

Bug Report

(I'm not 100% sure if this would count as a "bug report" or a "feature request", so feel free to correct me)

🔎 Search Terms

narrowing, type, template literal types, template strings, template literals

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about template literal types

⏯ Playground Link

Workbench Repro

💻 Code

// With template literal types
export type Action =
  | {
      type: `${string}_REQUEST`;
    }
  | {
      type: `${string}_SUCCESS`;
      response: string;
    };

export function reducer(action: Action) {
  if (action.type === 'FOO_SUCCESS') {
    console.log(action.response);
  }
}

// WITHOUT template literal types
export type Action2 =
  | {
      type: 'FOO_REQUEST';
    }
  | {
      type: 'FOO_SUCCESS';
      response: string;
    };

export function reducer2(action: Action2) {
  if (action.type === 'FOO_SUCCESS') {
    console.log(action.response);
  }
}

🙁 Actual behavior

In the example with template literal types in the reducer function, it seems like TypeScript is not able to narrow the type of action down, since accessing action.response results in the following error:

Property 'response' does not exist on type 'Action'.
  Property 'response' does not exist on type '{ type: `${string}_REQUEST`; }'.(2339)

While in the example without template literal types TypeScript is able to narrow down the type of Action correctly to the one with type: 'FOO_SUCCESS' and correctly recognizes that action.response can be safely accessed as expected.

🙂 Expected behavior

In the example with template literal types I expect TypeScript to be able to narrow the type of action down in the same way as it does in the example without template literal types, and not seeing any errors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fix AvailableA PR has been opened for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions