3 ms·
I just started a side project with Typescript, and I like a lot of it, but, ironically, type discovery seems _very_ lacking. The JS keywords like `instanceof` a
by pkulak 8y ago
I just started a side project with Typescript, and I like a lot of it, but, ironically, type discovery seems _very_ lacking. The JS keywords like `instanceof` are useless because everything is just an object, and Typescript doesn't give you a way to pattern match on types.
For example, in React there is this type that's a union of an array, single object or null. Some kind of catch-all, I guess. So, when you see one of these things, there's no way to know what you have unless you do something ugly like this:
if ((value as any).length) {
// it's an array
} else if (value) {
// must be a single object, I guess..
} else {
// null
}
The thought of littering my code with these kinds of type checks makes me feel really dirty, unless I'm totally missing something...
- srgpqt 8y agoYou’re not missing anything ; instanceof can be used to check prototype chain (class inheritance) but there is nothing similar for object interfaces (duck typing). And most Javascript objects are only loosely defined to conform to interfaces.
- stupidcar 8y agoWhat you're "missing", I think, is that Typescript's types only exist at compile-time, so they aren't available through runtime operations like instanceof. It's like a more extensive case of Java generics erasure.
- itslennysfault 8y agoUnless you use metadata reflection. Angular, NestJS, etc use this for dependency injection with great success.
- frankpf 8y agoFor types like those which are outside your control you can use type guards[1]: if (value == null) { // TS knows value is null, doesn't let you access value .length for example } else if (Array.isArray(value)) { // TS knows value is an array } else { // TS knows that it's an object here } However, having types like those in your own code (e.g. things like X[] | Y | null) is probably an antipattern and should be avoided. Using discriminated unions[2] is much better. [1]: https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types.... ("Type Guards and Differentiating Types" section) [2]: [1]: https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types.... ("Discriminated Unions" section)
- bmn__ 8y agoDeep links: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types https://www.typescriptlang.org/docs/handbook/advanced-types.... https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions https://www.typescriptlang.org/docs/handbook/advanced-types....
- spir 8y agoGood call. I love TypeScript, and wouldn't build a web app of even small scope without a typing solution at least as good as TypeScript, and it's the best. But, as you say, pattern matching sum types is a weak point in practical use of TypeScript. Since the types only exist at compile time, maybe there could be a heavier opt-in system that uses something like Symbols to do pattern matching: matchable type Shape = Circle | Square | Triangle; const myShape: Shape; match myShape { // uses symbol magic under the hood, eg. if (SymbolShapeCircle in o) case (c: Circle) { ... } case (other: Triangle | Square) { ... } }
- adrice727 8y agoIt's a far cry from actual pattern matching, but you can always tag your types[1]: interface Tagged { tag: string; } interface Circle extends Tagged { tag: 'circle' } // ... Other implementations switch (myShape.tag) { case 'circle': { // Do circular things } // etc . . . } You'll occasionally even see this in Scala code, since the @switch annotation optimizes pattern-match statements[2]. 1. https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions https://www.typescriptlang.org/docs/handbook/advanced-types.... 2. https://www.scala-lang.org/api/2.12.x/scala/annotation/switch.html https://www.scala-lang.org/api/2.12.x/scala/annotation/switc...
- karmakaze 8y agoMisclassifies an empty array as object since zero is falsy.