Git Product home page Git Product logo

Comments (11)

fatcerberus avatar fatcerberus commented on June 3, 2024 2

To clarify since this is a common point of confusion: { work: never } doesn't mean an object that never has a work property. It means an object that always has a work property whose value is type never. You can't legally create such an object at runtime since no such value exists.

from typescript.

MartinJohns avatar MartinJohns commented on June 3, 2024 2

It means an object that always has a work property whose value is type never. You can't legally create such an object at runtime since no such value exists.

Or a property that throws upon access. It's fine to create a throwing getter.

from typescript.

MartinJohns avatar MartinJohns commented on June 3, 2024 1

You still seem to mistakingly believe that having a never typed property makes it an "impossible value", but that's not the case.

type T = { value: never }
const t: T = { get value(): never { throw new Error() } }

from typescript.

fatcerberus avatar fatcerberus commented on June 3, 2024 1

I think you missed the implicit cast due to the type annotation in the function header 😉

That's not a cast, it's just a normal return type annotation. If JSON.parse() returned something other than any (like unknown), then the program would have had an error. The root of the issue in that particular example is that an unsound assignment to { work: never } isn't caught because the assignment source is any.

The bottom type means you can never access this value without throwing. As long as that invariant is maintained, then any assignment from never to any other type is sound, which is why the type system allows it.

from typescript.

fatcerberus avatar fatcerberus commented on June 3, 2024 1

Just in case someone finds this helpful: Instead of mapping the not JSONable keys to never, now, I map the whole type to never like JSONSerializable = T extends JSONValue ? T : never. This prevents false assignments.

The ideal solution for this use case would be #23689, but I don't know if we'll ever get it ☹️

from typescript.

shaman-apprentice avatar shaman-apprentice commented on June 3, 2024 1

awesome, I learned something. I agree that it works as intended and #23689 is the feature I am looking for. Thanks a lot for taking the time!

from typescript.

fatcerberus avatar fatcerberus commented on June 3, 2024

never is the bottom type and is intentionally assignable to all other types. This is because the type is an empty set and has no inhabitants - by definition you can never have a value of type never. If the return type of getLaborer were accurate, the function could never return normally since it's impossible to construct a LazyLaborer.

from typescript.

shaman-apprentice avatar shaman-apprentice commented on June 3, 2024

Thanks for your fast replies :)

It means an object that always has a work property whose value is type never. You can't legally create such an object at runtime since no such value exists.

That is exactly my point. Yet, the example creates such a value of the impossible LazyLaborer type and assigns it to a variable of the valid Laborer type. There is no way, the example would not produce an (unintended) runtime exception. Therefore, I expect TypeScript to not compile.

I fail to see, that assigning an impossible type to a possible type can be a correct, type safe assignment. I feel like, I am missing something here?

The LazyLaborer example is of course stupid. But the ability to write a function parse<T>(serializedValue: string): JSONSerializable<T> and having a compile error when I try to generate a not possible type, would be quite valuable to me.

from typescript.

fatcerberus avatar fatcerberus commented on June 3, 2024

The problem with the example, and why it’s not an error as written, is because JSON.parse returns any. That’s a separate issue; the part where { work: never } is assignable to { work: LiterallyAnythingElse } is working as intended. Normally you wouldn’t be able to assign anything to LazyLaborer without a compile error, but any is the “shut up and leave me alone, TypeScript” type. 😄

from typescript.

fatcerberus avatar fatcerberus commented on June 3, 2024

I fail to see, that assigning an impossible type to a possible type can be a correct, type safe assignment.

It’s a bit weird, but the mathematical explanation is that it’s the same as how the empty set is a subset of all other sets. More prosaically, if you have a function of type () => never, then that function by definition must always throw, so you can use it in place of () => T for any T. And since () => T is isomorphic to T

from typescript.

shaman-apprentice avatar shaman-apprentice commented on June 3, 2024

Long story short: We can close this issue as works as intended, right?

Thanks a lot for your detailed answers! :)

Nevertheless, I think it would be useful, if assigning an impossible value to something would be a caught error by the compiler. I see no intentional use of writing a program, whose static types cannot reflect its runtime types. From my point of view, programming languages should be useful and help me to prevent errors: In the example me.work() will lead to a runtime error, which could have been caught by the compiler. I mean, let i = 0; ... i = 1; ... is mathematically questionable, yet surely useful in a for loop 😜

Do you think a feature request for that would be valid? If not, I will trust your judgement 👍

P.S.:

The problem with the example, and why it’s not an error as written, is because JSON.parse returns any. That’s a separate issue;

I think you missed the implicit cast due to the type annotation in the function header 😉

P.P.S:

Just in case someone finds this helpful: Instead of mapping the not JSONable keys to never, now, I map the whole type to never like JSONSerializable<T> = T extends JSONValue ? T : never. This prevents false assignments.

from typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.