4 ms·
I think "unknown" is more than that! Basically it's a way to say you don't care about the type, as in Record<string, unknown> or P extends Promise<unknown>
by thoughtspile 4y ago
I think "unknown" is more than that! Basically it's a way to say you don't care about the type, as in Record<string, unknown> or P extends Promise<unknown>
- jax_the_dog 4y agoHow is unknown better than any in this case? If you do not care about the data type, wouldn’t you say that “any” data type is acceptable? If you say “unknown” that means that there is possibly some data type that would break your function.
- madeofpalk 4y agoThe problem with using any where you don't care about the type is that someone can come along and make unchecked assumptions about what type it actually is. Unknown is spicier as it'll prevent developers from assuming it's a string or object or something.
- jax_the_dog 4y agoThat makes some sense to me. I’m not a TypeScript dev so I apologize for the stupid question. Is there any functional difference between the two? I.e. is there a case where using Unknown instead of Any will result in some sort of “compile” time error opposed to a runtime?
- thoughtspile 4y agoAlmost every case where you use the value results in an error with unknown, but not with any: let danger: any; // These all compile: danger(), 9 / danger, danger.access, danger.map(x => x \* 2) let safe: unknown; // These all explode in TS: safe(), 9 / safe, safe.access, safe.map(x => x \* 2)
- madeofpalk 4y agoYes - trying to access a property or method on something typed as unknown will (almost?) always result in a compile time error because it's unknown whether the value has that property or not. https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABAdwE4EMAOBhBBnOAGwFMAZOAcwEEwBPACigAsYwKAVOcigLkXToBKRAG8AUIkQR8RYgDpClegCIAsrUQB1YgCNEVTJmUAaRM1YculOVDgBVQ8VTZ0eYvUGCxAXzFjQkLAIKBg4MiTcdmAA1mBwyGCMLGyc3HzgsfFgwuKS0mAEJApKahraegZGpuYpVhQ29o7Oru6ePn4B0PBIaFi4BbKRMXEJAELEUFBOSRaplOnDWTkSiDDAiIy0mMRw6zWW3IgAvCeIynhQqBbKy5J54fKKFCrqWrr6hiZmyQfWtg7bZpuDxeSTeRDEQhuUQre4DIpPF5ld6VL77OYUUGIXzeIA https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABAd...
- thoughtspile 4y agoalways, because "unknown" includes null / undefined, which don't allow property access at all.
- WorldMaker 4y agoYes. `any` really does turn off all type checking. You see that offhand mentioned in this article talking about some of the paradoxes of `any`. `unknown` is still type checked and is arguably "merciless" type-checked that to do much of anything with an `unknown` you have to check for a more specific type first or the compiler returns an error that what you are doing isn't known to be valid for `unknown`. Some of that happens "automatically" at this point in the large number of ways that types can now be narrowed implicitly in Typescript (type guards [library functions], type asserts, the `typeof` runtime operator, the `in` runtime operator [as of recently], etc), so it can feel like `unknown`/`any` are the same up to a point, that point being where the runtime type is trivially known based on if statements and library functions around your use of the type. (Fun fact: `any` predates most type narrowing and `unknown` by several major Typescript versions. So `any` beyond just being the final "escape hatch" from type checking is also something of a legacy tool.)
- thoughtspile 4y agoSaying a value is "unknown" means making no assumptions about the value. It might be a null, a number, a function, you don't care because you aren't going to do anything with this value. If you call() it, or read.some.property, TS complains because you're making assumptions about the object that TS did not ensure.
- edgyquant 4y agoBut you have to care about the type with unknown? For instance calling this on an unknown obj.value Will return a type error that value doesn’t exist on unknown. While calling it on an ant is valid typing
- thoughtspile 4y agoHere, you expect obj to have a property called "value", so I'd say you do care about the type of obj. A valid type would be obj: { value: blah }
- _greim_ 4y ago> But you have to care about the type with unknown? It's better to say `unknown` is a promise that you won't care about the type. When you write `obj.value`, you're caring about the type. TypeScript sees that and says "hey, you promised you wouldn't care about this type." > While calling it on an ant is valid typing It's still invalid, same as if you'd used `unknown`. It just suppresses the type error. The presence of `any` in a codebase is a very real risk. The only reason it exists is to allow incremental porting from JavaScript to TypeScript.
- sirmarksalot 4y agoThis is technically correct, but I suspect it's pretty rare that you would choose "unknown" over a generic parameter. Even if you're writing an algorithm that doesn't care about the data type, it's still probably going to be used by application code that does care, and you'll want to support that need by passing the type through, otherwise the application will be forced to downcast.
- thoughtspile 4y agoI often use it to infer one generic parameter: type Output<Fn> = Fn extends ((a: unknown) => infer Out) ? Out : never;