Skip to content

Unable to read properties off object spread in generic function parameter (regression with 4.6.1-rc) #47865

Closed
@danvk

Description

@danvk

Bug Report

I noticed a regression between TypeScript 4.6.0-beta and 4.6.1-rc in my repo where parameters to generic functions that use object spread sometimes get an unusable type.

🔎 Search Terms

  • object spread
  • 4.6.1-rc

🕗 Version & Regression Information

  • This changed between versions 4.6.0-beta and 4.6.1-rc.

⏯ Playground Link

Playground link with relevant code

💻 Code

(see comment below for a simpler repro: #47865 (comment))

/** Extract params from an express path (e.g. '/students/:studentId'). */
export type ExtractRouteParams<T extends string> = string extends T
  ? Record<string, string>
  : T extends `${infer _Start}:${infer Param}/${infer Rest}`
  ? {[k in Param | keyof ExtractRouteParams<Rest>]: string}
  : T extends `${infer _Start}:${infer Param}`
  ? {[k in Param]: string}
  : {};

declare function get<T extends string>(
  path: T,
  handler: (params: ExtractRouteParams<T>) => void,
): void;

get('/path/:foo/to/:bar', ({foo, ...slugs}) => {
  const {bar} = slugs;  // ok in TS 4.6.0-beta but not in TS 4.6.1-rc
  console.log({bar});
});

get('/path/:foo/to/:bar', slugs => {
  const {bar} = slugs;  // ok in both
  console.log({bar});
});

🙁 Actual behavior

Using object spread in a function parameter produces an unusable type in TS 4.6.1-rc.

The type of slugs in the first example is:

 slugs: { bar: string; }

in TypeScript 4.6.0-beta but:

slugs: Omit<ExtractRouteParams<T>, "foo">

in TypeScript 4.6.1-rc.

These are both the same (assuming T = "/path/:foo/to/:bar") but the latter doesn't let me read any properties off of it.

🙂 Expected behavior

I should be able to read bar off of slugs.

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