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

Regression: Type using conditional and mapped types is no longer assignable in 4.3 #44092

Closed
dragomirtitian opened this issue May 14, 2021 · 2 comments Β· Fixed by #44126
Closed
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.

Comments

@dragomirtitian
Copy link
Contributor

Bug Report

πŸ”Ž Search Terms

assignability regression

πŸ•— Version & Regression Information

  • This changed between versions 4.2 and 4.3-beta

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

export type UnrollOnHover<O extends object> = O extends object ?
    { [K in keyof O]: O[K]; } :
    never;


export type Schema = Record<string, unknown>;
class Table<S extends Schema>  {
    __schema!: S;

    // Removing this line, removes the error 
    getRows<C extends keyof S>(): Array<UnrollOnHover<Pick<S, C>>> {
        return null!
    }
}

class ColumnSelectViewImp<S extends Schema> extends Table<S> { }


const ColumnSelectView1: new <S extends Schema>() => Table<UnrollOnHover<S>> = ColumnSelectViewImp;
const ColumnSelectView2: new <S extends Schema>() => Table<UnrollOnHover<S>> = Table;

πŸ™ Actual behavior

Assignment to ColumnSelectView1 failed

πŸ™‚ Expected behavior

Assignment to ColumnSelectView1 succeeds as it did in 4.2

Workaround

Wrap S in UnrollOnHover as well Playground link

@weswigham
Copy link
Member

weswigham commented May 17, 2021

Yep, like I suspected, this was caused by a change in inference. Namely, we used to erase local type parameters to any, while now we map them into their constraints. So in earlier versions of TS, we'd replace C with any, resolve the Pick into an object with some index signatures, and match up the index signature type S[any] against UnrollOnHover<S>[string] (getting S = UnrollOnHover<S>, same as the other inference site). Now, UnrollOnHover remains unexecuted, because C is only replaced with keyof S., so instead, we're matching {[k: string]: S[any]} to UnrollOnHover<Pick<UnrollOnHover<S>, keyof UnrollOnHover<S>>>, which, when we look at the mapped type in UnrollOnHover, looks like {[K in keyof Pick<UnrollOnHover<S>, keyof UnrollOnHover<S>>]: Pick<UnrollOnHover<S>, keyof UnrollOnHover<S>>[K]} and wouldn't ya know, that template matches up to the index signature type and we match S to Pick<UnrollOnHover<S>, keyof UnrollOnHover<S>>.

The new inference is definitely valid (certainly, it's an expression of the same type, even if we don't always recognize it as such) - it's an inference we always could have made (albeit with more contortions), it's just really unfortunate, since it's at the same priority as the other inference site (and last-in-wins). I have put up a PR (#44126) that lowers the priority of the secondary inference site in structures like this one, so the mapped-over structure is a lower priority than the plain type parameter, which gets back the old inference and thus assignability behavior.

@dragomirtitian
Copy link
Contributor Author

@DanielRosenwasser @RyanCavanaugh This does not appear fixed in 4.3.2 (Playground Link) but works in nightly (Playground Link). Will there be a 4.3.3 where this will be included ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants