Doug Parker 🕸️ on Nostr: TypeScript does not enforce the types of "return only generics" so it accepts ...
TypeScript does not enforce the types of "return only generics" so it accepts whatever you give it. Like you mention, that's effectively a cast whether the developer knows it or not.
A recommended style I've seen is to avoid return only generics and just return `unknown` in such situations, forcing the developer to explicitly cast the result unambiguously.
The tricky part here is `| undefined` which you'd still want to enforce and would be subsumed by the `unknown`. I think you could do something like `{} | undefined` (not sure `{}` is the right type). But as soon as you require a cast you're losing the `undefined` constraint too.
```
const foo = getData('test', {noThrow: true}) as string;
// ^ Didn't handle `undefined`.
```
I think the best approach would be to return a `Result` type or discriminated union of some kind so it forces you to "unbox" the inner `unknown` by checking existence. I don't see a better way here.
A recommended style I've seen is to avoid return only generics and just return `unknown` in such situations, forcing the developer to explicitly cast the result unambiguously.
The tricky part here is `| undefined` which you'd still want to enforce and would be subsumed by the `unknown`. I think you could do something like `{} | undefined` (not sure `{}` is the right type). But as soon as you require a cast you're losing the `undefined` constraint too.
```
const foo = getData('test', {noThrow: true}) as string;
// ^ Didn't handle `undefined`.
```
I think the best approach would be to return a `Result` type or discriminated union of some kind so it forces you to "unbox" the inner `unknown` by checking existence. I don't see a better way here.