C'est le premier résultat que j'ai trouvé sur Google, alors je me suis dit que je devais fournir les solutions que j'ai trouvées.
Utilisation de bigint
Maintenant que nous sommes en 2020 et que bigint
a été acceptée, elle mérite d'être mentionnée. Vous pouvez simplement faire ce qui suit. Attention bigint
ont un impact plus important sur les performances par rapport à l'option number
.
const myNumber: bigint = 10n
Utilisation d'un type nominal / type balisé / type opaque
Une alternative est d'utiliser un type nominal, mais c'est sans doute moins ergonomique et je ne suis pas sûr que cela soit plus rapide que bigint
mais le modèle s'applique à n'importe quel type, et pas seulement à l'anglais. number
. TypeScript ne dispose pas d'une prise en charge "de première classe" pour cela, il faut donc faire un piratage insolent. Il existe une bibliothèque pour cela, appelée newtype-ts
qui comprend des types courants comme Integer
donc vous pouvez l'utiliser, mais je vais vous expliquer le fonctionnement ci-dessous.
Pour commencer, nous définissons le integer
type.
const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }
Le site TAG
assure que nous avons une valeur unique afin de ne pas créer accidentellement un objet avec la même clé, et nous faisons du champ un symbole unique aussi pour la même raison. Maintenant, votre entier n'aura pas réellement ce champ d'objet mais ce n'est pas grave.
Avec cela, vous pouvez encore ajouter integer
à number
en utilisant +
. Ce n'est pas bon. Donc vous pouvez renforcer la sécurité de type sur les arguments ici en massant le système de type avec une fonction. Je vais juste l'appeler guard, et encore une fois, comme vous pouvez le voir, ce n'est pas spécifique à integer
vous pourriez créer des types plus opaques et utiliser à nouveau cette méthode.
type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)
Si vous essayez de l'appeler avec un number
const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)
vous obtiendrez une erreur comme ci-dessous
Argument of type '10' is not assignable to parameter of type 'integer'.
Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)
Notez que vous n'imposez pas le type de retour ici (parce que vous devez utiliser la fonction as integer
) et certains opérateurs comme /
renverra des nombres à virgule flottante. Vous voudrez donc probablement effectuer des vérifications au moment de l'exécution ou ajouter une fonction Math.round
à une version spécialisée de guard
mais cela vous permettra au moins de vous assurer que vous n'essayez pas d'utiliser deux types numériques distincts ensemble - imaginez que vous avez GBP
y USD
et essayer de les ajouter, ce ne serait probablement pas ce que vous vouliez.