News for hackers. Stuff that matters.
Re:Adding type safety to object IDs in TypeScript by zokier on Tuesday January 30, 2024 @05:38PM (#39196903)
Its bit sad that startsWith doesn't narrow the type, making this pattern slightly less convenient. The GH issue: https://github.com/microsoft/TypeScript/issues/46958
Re:Adding type safety to object IDs in TypeScript by DylanSp on Tuesday January 30, 2024 @08:01PM (#39198335)
I wish that TS had better type narrowing for the JS standard library, though there's a lot of constraints and design limitations that make it impractical. I ran into a similar issue with the some() method on Array not narrowing types a while back [1]; that issue links to the same sort of issue with filter(), as well as issues where the TS team has discussed what they can and can't do in control flow analysis.

[1] https://github.com/microsoft/TypeScript/issues/40844

Re:Adding type safety to object IDs in TypeScript by EvertBouw on Wednesday January 31, 2024 @05:10AM (#39202004)
you can improve it a bit with the library ts-reset

https://github.com/total-typescript/ts-reset

Re:Adding type safety to object IDs in TypeScript by presentation on Wednesday January 31, 2024 @06:08AM (#39202398)
And also can declare your own wrappers to at least achieve it for your own codebase.
Re:Adding type safety to object IDs in TypeScript by mattigames on Tuesday January 30, 2024 @05:46PM (#39196995)
What is the problem with the workaround suggested in the last comment there?
Re:Adding type safety to object IDs in TypeScript by int_19h on Tuesday January 30, 2024 @06:18PM (#39197355)
You shouldn't need to write this kind of thing manually for every such type.
Re:Adding type safety to object IDs in TypeScript by ht85 on Wednesday January 31, 2024 @04:46AM (#39201880)

    function is<T extends string>(value: string, prefix: T): value is `${typeof prefix}_${string}` {
      return value.startsWith(`${prefix}_`)
    }

You can now do `is(id, 'user')`.

If you do that often you probably want to create separate functions, e.g.:

    function isFactory<T extends string>(prefix: T) {
      return (value: string) => is(value, prefix)
    }

    const isUser = isFactory('user')
    const isOrder = isFactory('order')
Not too bad.
Re:Adding type safety to object IDs in TypeScript by pcthrowaway on Tuesday January 30, 2024 @08:48PM (#39198701)
Define a type guard using a "type predicate"[1].

For example:

    type UserId = `user_${string}`;
    type GroupId = `group_${string}`;

    const addUserId = (id: UserId) => {
      // do something
    }

    const processId = (id: string) => {
      if (id.startsWith('user_') {
        // type error here:
        addUserId(id);
      } else if (otherCondition)
        // do other things
      }
    }
Instead you define a function:

    const isUserId = (some: string): some is UserId => some.startsWith('user_');
Now you can use it as follows:

    const processId = (id: string) => {
      if (isUserId(id)) {
        // no more error:
        addUserId(id);
      } else if (otherCondition)
        // do other things
      }
    }
[1]: https://www.typescriptlang.org/docs/handbook/2/narrowing.htm...