&& 연산자가 두 번째 피연산자의 유형을 생성하는 이유는 무엇입니까?
-
12-12-2019 - |
문제
TypeScript 사양은 §4.15.6에 다음과 같이 명시되어 있습니다. &&
운영자:
&& 연산자는 피연산자가 모든 유형이 되도록 허용하고 다음을 생성합니다. 두 번째 피연산자와 동일한 유형의 결과.
자바스크립트에서는 &&
연산자는 거짓이면 첫 번째 피연산자를 반환하고, 그렇지 않으면 두 번째 피연산자를 반환합니다(ECMA-262 §11.11 참조).
즉, 왼쪽 피연산자가 거짓이면 &&
왼쪽 피연산자의 유형과 일치하는 값을 반환합니다.예를 들어,
typeof ( false && {} ) === "boolean" // true
typeof ( '' && 1 ) === "string" // true
typeof ( null && "hello" ) === "object" // true
typeof ( NaN && true ) === "number" // true
위에 인용된 규칙에 따르면 Typescript는 다음과 같습니다. 틀리게 위 표현식의 유형을 예측해 보세요. Object
, Number
, String
그리고 Boolean
, 각각.
뭔가 빠졌나요?유형을 만드는 데에는 타당한 이유가 있습니까? &&
표현식이 두 번째 피연산자의 유형과 일치합니까?결과 유형이 다음과 같이 동작하면 안 되나요? ||
연산자를 사용하고 두 피연산자 중 가장 일반적인 유형을 반환합니다. Any
가장 좋은 공통 유형이 없다면?
해결책
간단히 말해서 모든 사람을 만족시킬 수 있는 해결책은 없습니다.
다음과 같은 일반적인 관용어를 고려해보세요.
var customer = GetCustomer(...); // of type 'Customer'
var address = customer && customer.address;
if(address) {
printAddressLabel(address); // Signature: (Address) => void
} else {
// Couldn't find the customer or the customer has no address on file
}
Customer와 Address 사이에 가장 공통적인 유형이 없기 때문에 포기하고 'address'가 'any'라고 결정하는 것은 매우 어리석은 일입니다.
&& 연산자가 사용되는 대부분의 경우 유형은 다음 중 하나입니다. 이미 match 또는 &&는 위와 같이 값 통합 방식으로 사용됩니다.두 경우 모두 오른쪽 피연산자의 유형을 반환하면 사용자에게 예상되는 유형이 제공됩니다.
이 시점에서 형식 안전성이 기술적으로 무너지고 있지만 오류가 발생할 가능성이 있는 방식은 아닙니다.결과 값의 진실성을 테스트하거나(이 경우 유형은 다소 관련이 없음) 일부 작업에 대해 추정 오른쪽 피연산자를 사용할 것입니다(둘 다 수행하는 위의 예).
나열된 예제를 보고 왼쪽 피연산자가 확실히 참인지 거짓인지 가정하고 반환 값에 대해 작동하는 정상적인 코드를 작성하려고 하면 훨씬 더 명확해집니다. 할 수 있는 일이 많지 않습니다. 하다 '모든' 인수 위치 또는 진실성 테스트에 아직 들어가지 않은 'false && {}'를 사용합니다.
부록
위의 내용을 납득하지 못하는 사람들도 있으므로, 여기에는 다른 설명이 있습니다.
TypeScript 유형 시스템에 세 가지 새로운 유형이 추가되었다고 잠시 가정해 보겠습니다. Truthy<T>
, Falsy<T>
, 그리고 Maybe<T>
, 유형의 가능한 진실/거짓 값을 나타냅니다. T
.이러한 유형에 대한 규칙은 다음과 같습니다.
Truthy<T>
정확히 다음과 같이 행동합니다T
- 다음 속성에 액세스할 수 없습니다.
Falsy<T>
- 유형의 표현
Maybe<T>
, 에서 조건으로 사용되는 경우if
블록은Truthy<T>
그 사람 몸에if
블록과Falsy<T>
에서else
차단하다
이렇게 하면 다음과 같은 작업을 수행할 수 있습니다.
function fn(x: Maybe<Customer>) {
if(x) {
console.log(x.address); // OK
} else {
console.log(x.phone); // Error: x is definitely falsy
}
console.log(x.name); // Warning: x might be falsy!
}
지금까지는 꽤 좋았습니다.이제 && 연산자에 대한 유형 규칙이 무엇인지 알아낼 수 있습니다.
Truthy<T> && x
오류여야 합니다. 왼쪽이 진실인 것으로 알려지면 방금 작성했어야 합니다.x
Falsy<T> && x
오류여야 합니다. 왼쪽이 거짓인 것으로 알려진 경우x
접근할 수 없는 코드입니다Maybe<T> && x
생산해야 한다...무엇?
우리는 그 결과를 알고 있다 Maybe<T> && x
유형의 잘못된 값이 됩니다. T
, 또는 x
.생산할 수 없습니다 Truthy<T>
(하지 않는 한 T
== 유형 x
어떤 경우에는 이 전체 논의가 문제가 됩니다.)이것을 새로운 유형이라고 부르자 Falsy<T> XOR Maybe<U>
.
규칙은 무엇이어야 하는가? Falsy<T> XOR Maybe<U>
BE?
- 분명히 다음의 속성을 사용할 수 없습니다.
T
그 위에.값이 유형인 경우T
, 그것은 거짓이며 사용하기에 안전하지 않습니다. - 으로 활용할 수 있어야 합니다.
Maybe<U>
, 부터Falsy<T>
그리고Falsy<U>
같은 행동을 가지고 - 다음의 속성을 사용할 수 없어야 합니다.
U
, 값이 여전히 거짓일 수 있기 때문입니다. - 당신이 그것을 사용하는 경우
if
테스트를 거쳐야 합니다.Truthy<U>
그 블록에if
성명
다시 말해서, Falsy<T> XOR Maybe<U>
~이다 Maybe<U>
.그것은 모두 동일한 규칙을 따릅니다.여기에 이런 이상한 문자를 추가하여 유형 시스템을 전혀 복잡하게 만들 필요가 없습니다. XOR
필요한 모든 사양에 맞는 유형이 이미 존재하기 때문입니다.
이는 누군가에게 상자를 주고 "이것은 빈 쓰레기 상자이거나 재활용품이 가득한 상자입니다"라고 말하는 것과 약간 비슷합니다.상자의 내용물을 재활용 쓰레기통에 안전하게 비울 수 있습니다.