Skip to content

T wider in lazy branch of T | (() => T) for known T #55277

Closed

Description

🔎 Search Terms

T | (() => T)
"T | (() => T)" inference
inference of lazy generic type
lazy generic inferred too wide

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about callbacks and functions and laziness and sum types.

⏯ Playground Link

https://www.typescriptlang.org/play?#code/C4TwDgpgBA8mwEsD2A7AhgGwyAMmgXiADwAqAfFALxQlQA+UAFIwJRUUksBQokUAsiBLho1AN5Q0ALigAjJEgwQ0KKAF8uAY1QBnYFABmq6o2Ay4iVJmx5CRQcMhk2lCmI1cjjCdKjAATgCuEAA0UDoAFkiBGAAmAGJoCBgyAIxqbAD0mVAAIhA6CP5oskqeKMwuFN6SMgHBYZHRcQZJKVAA5MARCDpQsUgFUChI+q3JYQDuPZoRUL1yaLEd6ixZOQBCS0A

💻 Code

type OptionallyLazy<T> = T | (() => T)
type MyType = { a: boolean }
const fn = (t: OptionallyLazy<MyType>) => {}

fn({ a: true, shouldFail: 'it does, good'})
fn(() => ({ a: true, shouldFail: 'this does not fail, which is bad' }))

🙁 Actual behavior

No type error for shouldFail on last line above.

🙂 Expected behavior

Type error for shouldFail on last line above, same as line above it.

Activity

  1. fatcerberus commented on Aug 5, 2023

    @fatcerberus

    () => MyTypeWithExtraProps is assignable to () => MyType, so this is working as intended. The error you see in the first case is due to the excess property check (EPC), which only applies to object literals directly assigned to a type. The error message for EPC is currently misleading; see #55152.

  2. RobertSandiford commented on Aug 5, 2023

    @RobertSandiford

    Discussed in some detail here #55113

    Objects are allowed to have additional properties, however special checks are applied in some locations just to catch probable bugs. As said in other places, this is more of a warning than a type error.

    Handbook: excess-property-checks

  3. pckilgore commented on Aug 5, 2023

    @pckilgore
    Author

    Ahh, appreciate the notes. I wish the error message for those checks were more clear they are a lint, and not a type system property. I've been operating under this misunderstanding for years writing TS!

    Any known good workarounds? I guess I can write a Lint rule to require annotation of a lazy value? This caused a very insidious misspelling bug.

    Thanks again.

  4. RobertSandiford commented on Aug 5, 2023

    @RobertSandiford

    Ahh, appreciate the notes. I wish the error message for those checks were more clear they are a lint, and not a type system property. I've been operating under this misunderstanding for years writing TS!

    Any known good workarounds? I guess I can write a Lint rule to require annotation of a lazy value? This caused a very insidious misspelling bug.

    Thanks again.

    I don't see any option other than explicit typings. There is an open suggestion (#12936) for Exact types that are always checked this way, maybe one day that will happen.

  5. fatcerberus commented on Aug 5, 2023

    @fatcerberus

    I wish the error message for those checks were more clear they are a lint, and not a type system property. I've been operating under this misunderstanding for years writing TS!

    You’re certainly not alone. Thats why I’m glad for #55152.

  6. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions