Live data from Hacker News

Tricks I wish I knew when I learned TypeScript

cstrnt.dev

51–60 of 276 posts

Re: Tricks I wish I knew when I learned TypeScript

#51
post #6

Note that `Readonly ` does not prevent a call to side-effect methods when `T` is not among a predefined set of built-in types. Indeed, it prevents such calls only on predefined types such as arrays, maps, and sets. It could be more "accurate" to use `readonly number[]` instead of `Readonly >` for highlighting the difference.

That example disappointed me a little.

It was an easy catch because I was told there's an issue, but I'm surprised const arrays don't at least have a warning there. Or even default to having readonly-like behavior

Re: Tricks I wish I knew when I learned TypeScript

#52
post #49

Earlier quoted context omitted.

a simple solution would be > if(entry && entry.constructor === Object){}

This isn't a great solution: entry = Object.create(null); entry.name = "Jason"; entry.age = 42; entry.constructor === Object // false - constructor is undefined. `entry` is a valid Human here, but fails your check. Actually, just creating a new class that implements the Human interface will cause a similar problem, since the constructor will be the class instead of Object. You don't even really want to exclude arrays…

I'm having some trouble finding your proposal in the thread... how would you do it?

Re: Tricks I wish I knew when I learned TypeScript

#53
post #47

The third example describes something useful in record types, but goes about it in what seems an odd way, and ends up suboptimal as a result. I'd instead use an object type like this: type Human = { name: string; age: number; } which also enforces value types in the compiler, rather than requiring runtime guards.

I think the example type is useful for unvalidated input data e.g. from an API call. Or an update function for a DB abstraction. Internally in the backend, you’d still use the type you just posited.

Eh. A good ORM provides type definitions from model definitions, which is one way I've found ORMs more useful in TS than JS, and I'd more likely use a runtype or a decoder to both validate and type inbound data than roll my own interface for it.

On review of documentation, I was actually pretty off base in grandparent comment. The real use case for Record appears to be when you need a map type whose keys are both explicitly enumerated and defined elsewhere, ie in a union, enum, or otherwise unrelated object type. Rather than duplicating the keys, you can use Record or Record and only have to make one change to update both.

For the "arbitrary keys, known value types" case I mentioned earlier, an object type with an index signature works fine and may be more legible.

Re: Tricks I wish I knew when I learned TypeScript

#54

Is there ever a reason to use interface over type? From what I’ve seen it looks like they can both do the same thing but with slight differences in syntax

“Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.” … “For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind…

You still can extend types with type intersections:

type A = { id: number }

type B = A & { name: string }

const b: B = { id: 0, name: 'foo' }

Re: Tricks I wish I knew when I learned TypeScript

#55
post #48
post #7

Earlier quoted context omitted.

Note: please post a better solution.

x && !Array.isArray(x) && typeof x === 'object'. its typical to start off with `var &&` to avoid operations on null & undefined values

For environment lacks Array.isArray method i think this works well

!!(x && x.__proto__ === [].__proto__)

Re: Tricks I wish I knew when I learned TypeScript

#56

Utility Types[0] will help you get to the next level on Typescript. It's important to know them and know how and when to use them. [0] https://www.typescriptlang.org/docs/handbook/utility-types.h...

Wow, thanks for this. I wasn't even aware of these.

I'm surprised I rarely see these in courses/tutorial. These should be like day 1 material.

Re: Tricks I wish I knew when I learned TypeScript

#57

The third example describes something useful in record types, but goes about it in what seems an odd way, and ends up suboptimal as a result. I'd instead use an object type like this: type Human = { name: string; age: number; } which also enforces value types in the compiler, rather than requiring runtime guards.

I found that pattern useful when you don't know what the key will be. I have an iOS app that tracks tips, when you add a tip, it's stored in an object like this:

type Tips = { [tipGuid: string]: TipObject }

which can be rewritten using Record as

type Tips = Record

That pattern ins't very useful when creating object with known keys but for data structures where the key is either not known or generated it a godsend.

Re: Tricks I wish I knew when I learned TypeScript

#58

Utility Types[0] will help you get to the next level on Typescript. It's important to know them and know how and when to use them. [0] https://www.typescriptlang.org/docs/handbook/utility-types.h...

Wow, thanks for this. I wasn't even aware of these. I'm surprised I rarely see these in courses/tutorial. These should be like day 1 material.

Typescript is actually a great language. And with those utility types, you can do pretty fun stuff like, for example, you want to mutate a type so that some fields become mandatory:

    type Ensure = T & { [U in keyof Pick]-?: T[U] };

    class A {
      foo?: number;
      bar?: number;
      baz?: number;
    }

    type MandatoryFields = "foo" | "baz";

    type B = Ensure;

    const b: B = { foo: 42 };
Here, ts will complain that b is missing baz.

Re: Tricks I wish I knew when I learned TypeScript

#59

The third example describes something useful in record types, but goes about it in what seems an odd way, and ends up suboptimal as a result. I'd instead use an object type like this: type Human = { name: string; age: number; } which also enforces value types in the compiler, rather than requiring runtime guards.

I found that pattern useful when you don't know what the key will be. I have an iOS app that tracks tips, when you add a tip, it's stored in an object like this: type Tips = { [tipGuid: string]: TipObject } which can be rewritten using Record as type Tips = Record That pattern ins't very useful when creating object with known keys but for data structures where the key is either not known or generated it a godsend.

While this is probably alright for some data, I'd definitely recommend using something like a Map instead (especially if the object mutates) for things you have control over (ie it's not describing an endpoint or something similar).

Re: Tricks I wish I knew when I learned TypeScript

#60

Earlier quoted context omitted.

You can declare Sometype|void return type. So the compiler will check that you either don't use the return type or treat it as Sometype. Of course this depends on the logic and for failed routes you should return appropriate results.

void implies that the return type should is undefined behavior and should not be relied upon, so that something like this const x = foo(); is incorrect when foo() returns void. 99% of the time x will be undefined (the value) but there are cases where it would not be. For example arr.forEach(x => x.sort()) sort returns a value as well as having a side effect. But forEach expects a void callback. This code is perfectly…

I agree. I don't see where what you wrote contradicts what I said.
Post reply on HN