Angular2 템플릿에서 안전한 연산자 ?.
는 작동하지만 component.ts
TypeScript 2.0 을 사용 하지는 않습니다 . 또한 안전한 탐색 연산자 (!.)가 작동하지 않습니다.
예를 들면 …
이 TypeScript
if (a!.b!.c) { }
이 JavaScript로 컴파일됩니다.
if (a.b.c) { }
하지만 실행하면 다음 오류가 발생합니다.
정의되지 않은 속성 ‘b’를 읽을 수 없습니다.
다음에 대한 대안이 있습니까?
if (a && a.b && a.b.c) { }
답변
TypeScript 3.7이 출시되었으므로 이제 선택적 연결을 사용할 수 있습니다.
속성 예 :
let x = foo?.bar.baz();
이것은 다음과 같습니다.
let x = (foo === null || foo === undefined) ?
undefined :
foo.bar.baz();
또한 다음을 호출 할 수 있습니다.
선택적 전화
function(otherFn: (par: string) => void) {
otherFn?.("some value");
}
otherFn은 otherFn이 null 또는 정의되지 않은 경우에만 호출됩니다.
IF 문에서 사용 선택적 연결
이:
if (someObj && someObj.someProperty) {
// ...
}
이제 이것으로 바꿀 수 있습니다
if (someObj?.someProperty) {
// ...
}
Ref. https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
답변
!
되는 null 이외의 주장 연산자 (후 수정 식) – 그냥 것을 검사기를 입력 할 말을 당신이있어 그 확실 a
하지 않다 null
나 undefined
.
작업
a!
은a
withnull
및undefined
excluded 유형의 값을 생성합니다.
선택적 연결은 마침내 typescript 로 만들었 습니다. ( 3.7 ) ?
선택적 연결 연산자를 사용
?.
하면 체인의 각 참조가 유효한지 명시 적으로 유효성을 검사 할 필요없이 연결된 개체의 체인 내 깊은 곳에있는 속성 값을 읽을 수 있습니다. 이?.
연산자.
는 참조가 nullish (null
또는undefined
) 인 경우 오류를 발생시키는 대신 표현식이 반환 값으로 단락 된다는 점을 제외 하면 연결 연산자 와 유사하게 작동합니다undefined
. 함수 호출과 함께 사용할 때undefined
주어진 함수가 존재하지 않으면 반환 합니다.
구문 :
obj?.prop // Accessing object's property
obj?.[expr] // Optional chaining with expressions
arr?.[index] // Array item access with optional chaining
func?.(args) // Optional chaining with function calls
주의 :
선택적 연결은 할당의 왼쪽에서 유효하지 않습니다.
const object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
답변
최신 정보:
3.7 릴리스 범위에서 계획 됨
https://github.com/microsoft/TypeScript/issues/33352
이와 같은 사용자 지정 함수를 작성해 볼 수 있습니다.
이 접근 방식의 주요 장점은 유형 검사와 부분적인 지능입니다.
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;
}
및 사용법 (최대 5 개의 매개 변수 지원 및 확장 가능) :
nullSafe(a, 'b', 'c');
놀이터의 예 .
답변
외부 라이브러리를 사용하는 또 다른 대안은 _.has () 에서 Lodash .
예
_.has(a, 'b.c')
동일하다
(a && a.b && a.b.c)
편집 : 주석에서 언급 했듯이이 방법을 사용할 때 Typescript의 유형 유추를 잃습니다. 예를 들어 개체가 올바르게 입력되었다고 가정하면 z가 개체 b의 필드로 정의되지 않으면 (a && ab && abz)와 함께 컴파일 오류가 발생합니다. 그러나 _.has (a, ‘b.z’)를 사용하면 해당 오류가 발생하지 않습니다.
답변
ts-optchain 이라는 새 라이브러리 는이 기능을 제공하며 lodash의 솔루션과 달리 유형을 안전하게 유지합니다. 다음은 사용 방법에 대한 샘플입니다 (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'))();
답변
@Pvl의 답변을 바탕으로 재정의를 사용하는 경우 반환 값에 유형 안전성을 포함 할 수 있습니다.
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;
}
놀이터의 예 .
답변
