IT story

Typescript가?를 지원합니까?

hot-time 2020. 4. 12. 10:33
반응형

Typescript가?를 지원합니까? 운영자? (그리고 그것이 무엇입니까?)


현재 Typescript가 안전한 탐색 연산자를 지원합니까 (또는 계획이 있습니까)?.

즉 :

var thing = foo?.bar
// same as:
var thing = (foo) ? foo.bar : null;

또한이 연산자의 일반적인 이름이 있습니까? (구글 적으로 구글하기가 어렵습니다).


TypeScript 언어 사양 에서 그것에 대한 참조를 찾을 수 없습니다 .

CoffeeScript에서이 연산자를 호출 할 때까지이를 실존 연산자 (특히 실존 연산자 의 "접근 변형 자")라고합니다.

에서 연산자에 커피 스크립트의 설명서 :

실재 연산자의 접근 자 변형을 ?.사용하여 일련의 속성에서 null 참조를 흡수 할 수 있습니다. .기본 값이 null 이거나 정의되지 않은 경우 도트 접근 자 대신 사용하십시오 .

따라서 실재 연산자접근 자 변형 이이 연산자를 참조하는 적절한 방법 인 것 같습니다. TypeScript는 현재 그것을 지원하지 않는 것으로 보입니다 ( 다른 사람들 이이 기능에 대한 욕구를 표현 했지만 ).


단일만큼 좋지는 않지만 작동합니다.

var thing = foo && foo.bar || null;

원하는만큼 &&을 (를) 사용할 수 있습니다.

var thing = foo && foo.bar && foo.bar.check && foo.bar.check.x || null;

이것은 ECMAScript Optional Chaining 사양에 정의되어 있으므로 이에 대해 논의 할 때 선택적인 Chaining을 참조해야 합니다. 아마도 구현 :

const result = a?.b?.c;

이것의 길고 짧은 것은 TypeScript 팀이 ECMAScript 사양이 강화되기를 기다리고 있기 때문에 향후 구현이 중단되지 않을 수 있다는 것입니다. 만약 그들이 지금 무언가를 구현한다면, ECMAScript가 그들의 사양을 재정의한다면 큰 변화가 필요할 것입니다.

선택적 체인 사양 참조

어떤 것이 표준 JavaScript가 될 수없는 경우 TypeScript 팀은 적절하다고 생각되는대로 구현할 수 있지만 향후 ECMAScript 추가를 위해 다른 많은 기능과 마찬가지로 조기 액세스를 제공하더라도 의미를 보존하려고합니다.

바로 가기

따라서 다음과 같은 유형 변환을 포함하여 모든 JavaScript 펑키 연산자를 사용할 수 있습니다.

var n: number = +myString; // convert to number
var b: bool = !!myString; // convert to bool

수동 솔루션

그러나 다시 질문으로 돌아갑니다. JavaScript (유형 TypeScript)에서 비슷한 작업을 수행하는 방법에 대한 모호한 예가 있지만 실제로 그 기능이 우아하다는 것은 확실하지 않습니다.

(foo||{}).bar;

그래서 경우가 foo있습니다 undefined결과 undefined및 경우 foo정의라는 이름의 속성이되는 bar값을 가지고, 결과는 그 값입니다.

나는 넣어 JSFiddle에 예 .

더 긴 예제에서는 꽤 스케치처럼 보입니다.

var postCode = ((person||{}).address||{}).postcode;

체인 기능

사양이 아직 공개되지 않은 상태에서 더 짧은 버전이 필사적이라면 경우에 따라이 방법을 사용합니다. 체인을 만족시킬 수 없거나 null / undefined로 끝나는 경우 표현식을 평가하고 기본값을 반환합니다 ( !=여기서는 중요합니다. 여기서 약간의 긍정적 인 저글링을 원하므로 사용하고 싶지 않습니다!== ).

function chain<T>(exp: () => T, d: T) {
    try {
        let val = exp();
        if (val != null) {
            return val;
        }
    } catch { }
    return d;
}

let obj1: { a?: { b?: string }} = {
    a: {
        b: 'c'
    }
};

// 'c'
console.log(chain(() => obj1.a.b, 'Nothing'));

obj1 = {
    a: {}
};

// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));

obj1 = {};

// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));

obj1 = null;

// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));

github에 대한 공개 기능 요청이 있습니다. 여기서 의견 / 욕구를 표현할 수 있습니다 : https://github.com/Microsoft/TypeScript/issues/16


편집 : fracz 의견 덕분에 답변을 업데이트했습니다.

TypeScript 2.0 출시 (C #의 Safe Navigator) !.와 동일하지 않음?.

자세한 내용은이 답변을 참조하십시오.

https://stackoverflow.com/a/38875179/1057052

이것은 컴파일러에게 그 값이 null 또는 undefined가 아니라고 알려줍니다. 이 것 없는 값이 null이거나 정의되어 있는지 확인하세요.

TypeScript 널이 아닌 어설 션 연산자

// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let s = e!.name;  // Assert that e is non-null and access name
}

?.TypeScript 버전 2.0 에서는 연산자 가 지원되지 않습니다 .

그래서 나는 다음 기능을 사용합니다 :

export function o<T>(someObject: T, defaultValue: T = {} as T) : T {
    if (typeof someObject === 'undefined' || someObject === null)
        return defaultValue;
    else
        return someObject;
}

사용법은 다음과 같습니다.

o(o(o(test).prop1).prop2

또한 기본값을 설정할 수 있습니다.

o(o(o(o(test).prop1).prop2, "none")

Visual Studio에서 IntelliSense와 잘 작동합니다.


Phonetradr에서 작업하는 동안이 util 메소드를 작성 하여 Typescript를 사용하여 딥 속성에 안전하게 액세스 할 수 있습니다.

/**
 * Type-safe access of deep property of an object
 *
 * @param obj                   Object to get deep property
 * @param unsafeDataOperation   Function that returns the deep property
 * @param valueIfFail           Value to return in case if there is no such property
 */
export function getInSafe<O,T>(obj: O, unsafeDataOperation: (x: O) => T, valueIfFail?: any) : T {
    try {
        return unsafeDataOperation(obj)
    } catch (error) {
        return valueIfFail;
    }
}

//Example usage:
getInSafe(sellTicket, x => x.phoneDetails.imeiNumber, '');

//Example from above
getInSafe(foo, x => x.bar.check, null);


일반적으로이 방법을 권장하지는 않지만 (성능 문제를 조심하십시오) 스프레드 연산자를 사용하여 객체를 얕게 복제 한 다음 속성에 액세스 할 수 있습니다.

 const person = { personId: 123, firstName: 'Simon' };
 const firstName = { ...person }.firstName;

'firstName'의 유형이 '전파'되었기 때문에 작동합니다.

find(...)null을 반환 할 수 있는 표현식이 있고 단일 속성이 필요할 때 이것을 가장 자주 사용 합니다.

 // this would cause an error (this ID doesn't exist)
 const people = [person];
 const firstName2 = people.find(p => p.personId == 999).firstName;

 // this works - but copies every property over so raises performance concerns
 const firstName3 = { ...people.find(p => p.personId == 999) }.firstName;

typescript가 형식을 유추하는 방식과 관련된 일부 경우가있을 수 있으며 컴파일되지는 않지만 일반적으로 작동합니다.


Elvis (?) 연산자는 TypeScript 3.7에서 지원됩니다.

이 값을 사용하여 null 값을 확인할 수 있습니다 cats?.miows. cats가 null이거나 정의되지 않은 경우 null을 반환합니다.

선택적 메소드 호출에 사용할 수도 cats.doMiow?(5)있습니다. 존재하는 경우 doMiow를 호출합니다.

참조 : https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/


이전에 대답했듯이, 현재도 여전히 고려되고 있지만 지금까지 몇 년 동안 물에서 죽었습니다 .

기존 답변을 바탕으로 생각할 수 있는 가장 간결한 수동 버전이 있습니다.

jsfiddle

function val<T>(valueSupplier: () => T): T {
  try { return valueSupplier(); } catch (err) { return undefined; }
}

let obj1: { a?: { b?: string }} = { a: { b: 'c' } };
console.log(val(() => obj1.a.b)); // 'c'

obj1 = { a: {} };
console.log(val(() => obj1.a.b)); // undefined
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

obj1 = {};
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

obj1 = null;
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

누락 된 속성 오류로 인해 자동으로 실패합니다. 기본값을 결정하는 표준 구문으로 돌아가며 완전히 생략 할 수 있습니다.


이것은 간단한 경우에 효과적이지만 함수 호출과 같은 더 복잡한 작업이 필요하고 결과의 속성에 액세스하면 다른 오류도 삼킨다. 나쁜 디자인.

위의 경우 여기에 게시 된 다른 답변의 최적화 된 버전이 더 나은 옵션입니다.

jsfiddle

function o<T>(obj?: T, def: T = {} as T): T {
    return obj || def;
}

let obj1: { a?: { b?: string }} = { a: { b: 'c' } };
console.log(o(o(o(obj1).a)).b); // 'c'

obj1 = { a: {} };
console.log(o(o(o(obj1).a)).b); // undefined
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

obj1 = {};
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

obj1 = null;
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

더 복잡한 예 :

o(foo(), []).map((n) => n.id)

다른 방법으로 가서 Lodash '와 같은 것을 사용할 수도 있습니다 _.get(). 간결하지만 컴파일러는 사용 된 속성의 유효성을 판단 할 수 없습니다.

console.log(_.get(obj1, 'a.b.c'));

아직 (2019 년 9 월 현재), "안전한 탐색 연산자" 가 이제 Stage 3 에 있으므로 TypeScript에서 구현되고 있습니다.

이 문제를보고 업데이트하십시오.

https://github.com/microsoft/TypeScript/issues/16

몇몇 엔진에는 초기 구현이 있습니다.

JSC : https://bugs.webkit.org/show_bug.cgi?id=200199

V8 : https://bugs.chromium.org/p/v8/issues/detail?id=9553

SM : https://bugzilla.mozilla.org/show_bug.cgi?id=1566143

( https://github.com/tc39/proposal-optional-chaining/issues/115#issue-475422578을 통해 )

지금 지원하기 위해 플러그인을 설치할 수 있습니다 :

npm install --save-dev ts-optchain

tsconfig.json에서 :

// tsconfig.json
{
    "compilerOptions": {
        "plugins": [
            { "transform": "ts-optchain/transform" },
        ]
    },
}

6 개월 정도 지나면이 답변이 만료 될 것으로 예상되지만 그 동안 누군가에게 도움이 되길 바랍니다.


_.get(obj, 'address.street.name')유형이없는 JavaScript에 적합합니다. 그러나 TypeScript 에는 실제 Elvis 연산자 가 필요 합니다!

참고 URL : https://stackoverflow.com/questions/15260732/does-typescript-support-the-operator-and-whats-it-called

반응형