Dans TypeScript, existe-t-il un type pour véridique?
J'ai cette méthode: Object.keys (lck.lockholders) .length; enqueue (k: any, obj ?: any): void think with TS there is a way to check for empty strings '', soit dit en passant. et je veux le convertir en:
enqueue(k: Truthy, obj?: any): void
sauf que je ne sais pas comment définir le type de Truthy. I pensez avec TS qu'il y a un moyen de vérifier les chaînes vides '', soit dit en passant.
La raison pour laquelle je veux cela est parce que je ne veux pas que les utilisateurs passent null
, undefined
, ''
, etc., comme clé d'un hachage.
Je ne sais pas pourquoi vous en avez besoin, mais c'est intéressant. En toute honnêteté, la réponse courte est: TypeScript n'est pas conçu pour cela et vous feriez probablement mieux de faire des vérifications d'exécution et de documenter votre code afin que les développeurs soient conscients que le paramètre k
doit être véridique. Pourtant, si vous essayez de forcer TypeScript à faire quelque chose comme ça, lisez la suite:
Remarque: pour que ce qui suit fonctionne, activez l'option de compilateur strictNullChecks
. C'est un peu nécessaire, car être incapable de distinguer Truthy
de Truthy | null | undefined
Serait un problème.
Vous pouvez presque définir falsy , ce qui est comme
type Falsy = false | 0 | "" | null | undefined
sauf NaN
est également faux, et TypeScript n'a pas un littéral numérique pour NaN
.
Même si vous avez Falsy
comme ci-dessus, il n'y a pas types niés dans TypeScript, donc il n'y a aucun moyen d'exprimer Truthy
comme "tout sauf Falsy
".
Vous pouvez essayer d'utiliser use types conditionnels pour exclure les paramètres potentiellement faux dans enqueue()
, mais c'est bizarre:
type DefinitelyTruthy<T> =
false extends T ? never :
0 extends T ? never :
"" extends T ? never :
null extends T ? never :
undefined extends T ? never :
T
declare function enqueue<T extends number | string | true | object>(
k: T & DefinitelyTruthy<T>,
obj?: any
): void
declare const str: string;
enqueue(str); // error, might be falsy
enqueue("a"); // okay
enqueue(1); // okay
enqueue(0); // error
enqueue(NaN); // error
enqueue(true); // okay
enqueue(false); // error
enqueue([]); //okay
enqueue({a: "hello"}); // okay
enqueue({}); // error, interpreted as type {} which could be an empty string:
const zilch = "" as {};
enqueue(zilch); // error, see?
Notez comment il ne permettra rien de ce qu'il pense pourrait être faux, ce qui est probablement ce que vous essayez de réaliser. Je ne sais pas.
Je vois que vous avez modifié la question pour clarifier que le paramètre k
devrait vraiment être un string
(ou peut-être un symbol
) et que la seule valeur que vous devez exclure est le vide chaîne ""
. Dans ce cas, vous pouvez simplifier ce qui précède pour:
type DefinitelyNotEmptyString<T> = "" extends T ? never : T
declare function enqueue<T extends string | symbol>(
k: T & DefinitelyNotEmptyString<T>,
obj?: any
): void
enqueue(""); // error
enqueue("a"); // okay
Tout cela est génial, mais malheureusement, il y a le problème que si vous passez un string
à enqueue()
général, il échouera, et parfois un développeur pourrait avoir besoin de le faire si la valeur qu'il utilise pour le paramètre k
n'est pas un littéral de chaîne qu'ils ont spécifié:
declare const str: string; // comes from somewhere else
enqueue(str); // error! how do I do this?
Pour y faire face, vous pouvez essayer de créer un type nominal que vous pouvez utiliser pour identifier au compilateur qu'une valeur a été vérifiée pour la vacuité, puis faire un type défini par l'utilisateur guard pour contraindre un string
à ce type:
type NotEmptyString = string & {"***NotEmptyString***": true};
function notEmptyString(x: string): x is NotEmptyString {
return x !== "";
}
Maintenant, le développeur peut le faire:
declare const str: string;
enqueue(str); // error, might be falsy
if (notEmptyString(str)) {
enqueue(str); // okay, str is NotEmptyString
}
Ouf! Cela fait beaucoup de sauts de cerceau. Cela dépend de vous si vous pensez que cela en vaut la peine. D'accord, j'espère que ça aide. Bonne chance!
Il n'y a pas de type Truthy
, [~ # ~] mais [~ # ~] vous pouvez utiliser le système de protection de type ( type prédicat ) pour aider TypeScript à comprendre ce qu'est vraiment truthy
et à lui affecter truthy
type!
Définissons le type Falsy
et la fonction génériqueisTruthy
:
type Falsy = false | 0 | '' | null | undefined;
// this is a type predicate - if x is `truthy`, then it's T
const isTruthy = <T>(x: T | Falsy): x is T => !!x;
Maintenant, nous pouvons utiliser la fonction out isTruthy
pour trouver les valeurs truthy
et TypeScript attribuera correctement le "truthy"
tapez le résultat.
Exemples:
{ // removing boolean "false" type
const result: string | false = Math.random() > 0.5 ? 'a' : false;
const truthyResult: string = isTruthy(result) ? result : 'was false';
}
{ // filtering only numbers from array
const result: (number | undefined)[] = [42, undefined, 8, 16];
const truthyResult: number[] = result.filter(isTruthy);
}
{ // filtering only Promises from array
const result: (Promise<string> | null)[] = [Promise.resolve('a'), null, Promise.resolve('b'), Promise.resolve('c')];
const truthyResult: Promise<string>[] = result.filter(isTruthy);
}