Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.23.0 introduced a breaking change in Paths type #922

Closed
mwaibel-go opened this issue Jul 24, 2024 · 6 comments
Closed

4.23.0 introduced a breaking change in Paths type #922

mwaibel-go opened this issue Jul 24, 2024 · 6 comments

Comments

@mwaibel-go
Copy link

mwaibel-go commented Jul 24, 2024

I get this error with type-fest 4.23.0 that I didn’t get with 4.22.1:

Type 'string' is not assignable to type 'never'.(2322)
main.ts(3, 3): The expected type comes from property 'column' which is declared here on type 'ColumnSortState<Record<any, any>>'

Offending code (Stackblitz):

import { Paths } from "type-fest";
interface ColumnSortState<Sortee extends object> {
  column: Paths<Sortee>;
}


function sort<Sortee extends Properties, Properties extends Record<any, any>>(
  _sortees: Sortee[],
  _sortState: ColumnSortState<Properties>,
): void {
}


interface Dto {
  startDate: string
}
let dtos!: Dto[]
sort(
  dtos,
  {
    column: 'startDate',
  }
)

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@mwaibel-go mwaibel-go changed the title 4.23.0 introduced a breaking change 4.23.0 introduced a breaking change in Paths type Jul 24, 2024
@sindresorhus
Copy link
Owner

// @fardolieri

@voxpelli
Copy link
Collaborator

The change causing the regression: #920

@voxpelli
Copy link
Collaborator

Why do sort<Sortee extends Properties, Properties extends Record<any, any>> rather than just sort<Sortee extends Record<any, any>>?

@fardolieri
Copy link
Contributor

Oh that is really interesting. I created a trimmed down version that shows the problem Playground Link

The example of @mwaibel-go only worked with the old version of Paths because they abused a side effect where a (strange looking) Type could be inferred from a given input path.

If we look at the example sortOld({ foo: '' }, 'bar') then the error message is

'foo' does not exist in type '{ bar: any; } & { bar: any; } & { bar: any; } & { bar: any; } & { bar: any; } & { bar: any; } & { bar: any; } & { bar: any; }'.

Meaning that typescript could go the reverse direction and create a type {bar: any} (simplified) from the input 'bar'. But this breaks on the first attempt of nesting, see sortOld({ foo: {bar: ''} }, 'foo.bar'). The type being inferred from foo.bar is { "foo.bar": any; } & { foo: any; } which is missing { foo: { bar: any } }. That means the example never even worked with nested paths, which is the whole point of Paths. If you only need "one layer" you can use keyof T.

TLDR; The way @mwaibel-go used Paths<T> only allowed keys that are one layer deep, which is the same as keyof T. If you want the exact same behavior as before:

import { Paths } from "type-fest";
interface ColumnSortState<Sortee extends object> {
- column: Paths<Sortee>;
+ column: keyof Sortee;
}


function sort<Sortee extends Properties, Properties extends Record<any, any>>(
  _sortees: Sortee[],
  _sortState: ColumnSortState<Properties>,
): void {}

If you actually want to use Paths<T> and allow multi layered keys:

function sort<Sortee extends Record<any, any>>(
  _sortees: Sortee[],
  _sortState: ColumnSortState<Sortee>,
): void {}

@bleistift-zwei
Copy link

bleistift-zwei commented Jul 25, 2024

This is mwaibel-go’s alt account speaking.

Why do sort<Sortee extends Properties, Properties extends Record<any, any>> rather than just sort<Sortee extends Record<any, any>>?

It’s a minimal example. The original function requires access to both Sortee and Properties, @voxpelli.

The way @mwaibel-go used Paths only allowed keys that are one layer deep, which is the same as keyof T.

That is interesting. I will need to check if my code has just been broken ever since, or if this is a result of creating a MWE. Thanks for pointing that out.

@sindresorhus If you’d like to keep your issue queue small, you can close this. I will then create a new issue if I can find a reproduction that doesn’t involve broken code. Otherwise, I’ll respond again in about a week, since I’m on vacation right now.

@mwaibel-go
Copy link
Author

I’m sorry for the noise. I cannot reproduce the error. Thanks for pointing out the issue in my code, @fardolieri!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants