5

I want to create two types in TypeScript, both of them are a number:

export type GlobalPortIndex = number;
export type TypePortIndex = number;

As far as I understand, TypeScript will consider these mutually compatible since they overlap perfectly.

But I want them to be incompatible, so when I type something GlobalPortIndex, then if I try to assign a TypePortIndex to it, I'd get a type error. This is to make sure I don't mix them up in the code, for example I can't pass one to a function that expects the other.

Any TypeScript tricks to achieve this?

  • 1
    Are you familiar with the term of art here, "[nominal typing](https://betterprogramming.pub/nominal-typescript-eee36e9432d2)", and the common solutions of adding a fake non-runtime property as a "tag" or "brand"? – Jeff Bowman Jun 21 '21 at 22:41

3 Answers3

1

You need to declare additional property (or method) to make the 2 classes different:

class GlobalPointerIndex extends Number {
  __GlobalPointerIndex: boolean;
}

class TypePortIndex extends Number {
  __TypePortIndex: boolean;
}
Z .
  • 12,657
  • 1
  • 31
  • 56
0

I am no expert on typescript, but wouldn't it be better if you actually wrap the value into class and then static check class type?

Since it looks like you have a object type as GlobalPortIndex, and the other one is TypePortIndex, they serve a different purpose.

Or perhaps set them as enum syntax can resolve this issue?

enum FooKeys {
  FOO = 'foo',
  BAR = 'bar',
}

// probably all you need, but it's a type alias
type FooType = Record<FooKeys, string>;

The code above is referenced from this post: How to build a type from enum values in TypeScript?

GoldenArcher
  • 812
  • 1
  • 9
  • 12
-1

try this:

export interface GlobalPortIndex {
brand : 'GlobalPortIndex';
value : number;
}

export interface TypePortIndex {
brand : 'TypePortIndex';
value : number;
}

but you have to use it like :

const myport = {value:25} as TypePortIndex

and access to value like myport.value