Les modèles Angular2 ont un opérateur sécurisé (?.), Mais dans Component.ts (TypeScript 2.0) Opérateur de navigation sûr (!.) Ne fonctionne pas.
Exemple:
Ce typeScript
if (a!.b!.c) { }
compile à ce JavaScript
if (a.b.c) { }
Mais quand je le lance, j'obtiens l'erreur suivante:
Impossible de lire la propriété 'b' de non définie
Y a-t-il une alternative à:
if (a && a.b && a.b.c) { }
?
Il n'y a actuellement aucun opérateur de navigation sûr dans TypeScript (toujours dans discussion ).
!.
est un opérateur d'assertion non nul. Il indique simplement à un vérificateur que vous êtes sûr que a
n'est pas null
ou undefined
.
Plus d'infos ici
Vous pouvez essayer d'écrire une fonction personnalisée comme ça.
Le principal avantage de cette approche est une vérification de type et un intellisense partiel.
export function nullSafe<T,
K0 extends keyof T,
K1 extends keyof T[K0],
K2 extends keyof T[K0][K1],
K3 extends keyof T[K0][K1][K2],
K4 extends keyof T[K0][K1][K2][K3],
K5 extends keyof T[K0][K1][K2][K3][K4]>
(obj: T, k0: K0, k1?: K1, k2?: K2, k3?: K3, k4?: K4, k5?: K5) {
let result: any = obj;
const keysCount = arguments.length - 1;
for (var i = 1; i <= keysCount; i++) {
if (result === null || result === undefined) return result;
result = result[arguments[i]];
}
return result;
}
Et utilisation (prend en charge jusqu'à 5 paramètres et peut être étendue):
nullSafe(a, 'b', 'c');
Exemple sur playground .
Une nouvelle bibliothèque appeléets-optchainfournit cette fonctionnalité, et contrairement à la solution lodash ', elle protège également vos types, voici un exemple de la façon dont elle est utilisée (extraite du readme):
import { oc } from 'ts-optchain';
interface I {
a?: string;
b?: {
d?: string;
};
c?: Array<{
u?: {
v?: number;
};
}>;
e?: {
f?: string;
g?: () => string;
};
}
const x: I = {
a: 'hello',
b: {
d: 'world',
},
c: [{ u: { v: -100 } }, { u: { v: 200 } }, {}, { u: { v: -300 } }],
};
// Here are a few examples of deep object traversal using (a) optional chaining vs
// (b) logic expressions. Each of the following pairs are equivalent in
// result. Note how the benefits of optional chaining accrue with
// the depth and complexity of the traversal.
oc(x).a(); // 'hello'
x.a;
oc(x).b.d(); // 'world'
x.b && x.b.d;
oc(x).c[0].u.v(); // -100
x.c && x.c[0] && x.c[0].u && x.c[0].u.v;
oc(x).c[100].u.v(); // undefined
x.c && x.c[100] && x.c[100].u && x.c[100].u.v;
oc(x).c[100].u.v(1234); // 1234
(x.c && x.c[100] && x.c[100].u && x.c[100].u.v) || 1234;
oc(x).e.f(); // undefined
x.e && x.e.f;
oc(x).e.f('optional default value'); // 'optional default value'
(x.e && x.e.f) || 'optional default value';
// NOTE: working with function value types can be risky. Additional run-time
// checks to verify that object types are functions before invocation are advised!
oc(x).e.g(() => 'Yo Yo')(); // 'Yo Yo'
((x.e && x.e.g) || (() => 'Yo Yo'))();
En vous appuyant sur la réponse de @ Pvl, vous pouvez également inclure la sécurité de type dans votre valeur renvoyée si vous utilisez des substitutions:
function Dig<
T,
K1 extends keyof T
>(obj: T, key1: K1): T[K1];
function Dig<
T,
K1 extends keyof T,
K2 extends keyof T[K1]
>(obj: T, key1: K1, key2: K2): T[K1][K2];
function Dig<
T,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2]
>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function Dig<
T,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2],
K4 extends keyof T[K1][K2][K3]
>(obj: T, key1: K1, key2: K2, key3: K3, key4: K4): T[K1][K2][K3][K4];
function Dig<
T,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2],
K4 extends keyof T[K1][K2][K3],
K5 extends keyof T[K1][K2][K3][K4]
>(obj: T, key1: K1, key2: K2, key3: K3, key4: K4, key5: K5): T[K1][K2][K3][K4][K5];
function Dig<
T,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2],
K4 extends keyof T[K1][K2][K3],
K5 extends keyof T[K1][K2][K3][K4]
>(obj: T, key1: K1, key2?: K2, key3?: K3, key4?: K4, key5?: K5):
T[K1] |
T[K1][K2] |
T[K1][K2][K3] |
T[K1][K2][K3][K4] |
T[K1][K2][K3][K4][K5] {
let value: any = obj && obj[key1];
if (key2) {
value = value && value[key2];
}
if (key3) {
value = value && value[key3];
}
if (key4) {
value = value && value[key4];
}
if (key5) {
value = value && value[key5];
}
return value;
}
Exemple sur playground .