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

#39258's stricter assignability breaks vue-next #40725

Closed
sandersn opened this issue Sep 23, 2020 · 3 comments
Closed

#39258's stricter assignability breaks vue-next #40725

sandersn opened this issue Sep 23, 2020 · 3 comments
Assignees
Labels
Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros

Comments

@sandersn
Copy link
Member

sandersn commented Sep 23, 2020

This may be intended, but I want a bug to track this in case others run into it.

// @strict: true
export interface Ref<T = any> { value: T }
type UnwrapRef<T> = T extends Ref<infer V> ? V : never
declare function readonly<T>(target: T): UnwrapRef<T>

const toReadonly = <T extends unknown>(value: T): T =>
    // readonly(value as T & Record<any,any>)
  isObject(value) ? readonly(value) : value

declare function isObject(val: unknown): val is Record<any, any>

This is an error without --strict on 4.0, but not with --strict. In 4.1, it's an error for both.

Expected behavior:

No error and value: Record<any, any> in readonly(value).

Actual behavior:

Error and value: T & Record<any, any> in readonly(value):

Type 'T | UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'.
  'T | UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'.
    Type 'UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'.
      'UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'.
        Type 'unknown' is not assignable to type 'T'.
          'unknown' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'.

Also I'm not sure where the last two lines of the error come from. They don't seem to follow from the previous lines.

Workaround

readonly(value as Record<any, any>) to restore the old type of value: casting to subtype is allowed.

@sandersn sandersn added this to the TypeScript 4.1.1 milestone Sep 23, 2020
@typescript-bot typescript-bot added the Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros label Sep 23, 2020
@typescript-bot
Copy link
Collaborator

typescript-bot commented Sep 24, 2020

👋 Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in this issue running against the nightly TypeScript. If something changes, I will post a new comment.


Issue body code block by @sandersn

❌ Failed: -

  • Type 'T | UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'. 'T | UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. Type 'UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'. 'UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. Type 'unknown' is not assignable to type 'T'. 'unknown' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'.

Historical Information

Issue body code block by @sandersn

Version Reproduction Outputs
Nightly

❌ Failed: -

  • Type 'T | UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'. 'T | UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. Type 'UnwrapRef<T & Record<any, any>>' is not assignable to type 'T'. 'UnwrapRef<T & Record<any, any>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. Type 'unknown' is not assignable to type 'T'. 'unknown' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'.

3.5.3, 3.6.4, 3.7.5, 3.8.3, 3.9.5

👍 Compiled

@orta
Copy link
Contributor

orta commented Sep 29, 2020

So, we think this is a real compiler error that used to be masked - 4.0 and and below would effectively give an any for the T side of the compiler error previously

const toReadonly = <T extends unknown>(value: T): T =>
    // readonly(value as T & Record<any,any>)
  isObject(value) ? readonly(value) : value

Effectively gives either { value: 123} or 123 which aren't assignable - thus the error is legit 👍🏻

@orta orta closed this as completed Sep 29, 2020
@sandersn
Copy link
Member Author

My workaround also made it into vue-next yesterday: vuejs/core#2219

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros
Projects
None yet
Development

No branches or pull requests

3 participants