“오류 TS2533 : 개체가 'null'또는 'undefined'일 수 있습니다.”를 억제하는 방법은 무엇입니까?


225

나는 type:

type tSelectProtected = {
  handleSelector?: string,
  data?: tSelectDataItem[],

  wrapperEle?: HTMLElement,
  inputEle?: HTMLElement,
  listEle?: HTMLElement,
  resultEle?: HTMLElement,

  maxVisibleListItems?: number
}

전역 모듈 단위 변수를 선언합니다.

var $protected : tSelectProtected = {};

function1()범위 에서 적절한 가치를 부여하고 있습니다 .

$protected.listEle = document.createElement('DIV');

나중에 function2()범위 내에서 전화합니다.

$protected.listEle.classList.add('visible');

TypeScript 오류가 발생합니다.

error TS2533: Object is possibly 'null' or 'undefined'

if ($protected.listEle) {$protected.listEle}컴파일러를 진정시키기 위해 명시 적으로 검사를 수행 할 수 있지만 대부분의 사소한 경우에는 매우 적합하지 않은 것 같습니다.

TS 컴파일러 검사를 비활성화하지 않고 어떻게이 상황을 처리 할 수 ​​있습니까?

답변:


99

이 기능은 --strictNullChecks컴파일러 플래그가 설정되어 있지 않은지 확인하기 위해 "엄격한 널 검사"라고 합니다.

그러나 존재 null했다 설명한 바와 같이 억 달러 실수 이므로 같은 타이프가 수정 도입 같은 언어를 표시 흥미 롭다. 전원을 켜두는 것이 좋습니다.

이 문제를 해결하는 한 가지 방법 은 예를 들어 값 을 미리 초기화 하여 값이 절대 null또는 아닌지 확인하는 undefined것입니다.

interface SelectProtected {
    readonly wrapperElement: HTMLDivElement;
    readonly inputElement: HTMLInputElement;
}

const selectProtected: SelectProtected = {
    wrapperElement: document.createElement("div"),
    inputElement: document.createElement("input")
};

그러나 대안 옵션에 대해서는 Ryan Cavanaugh의 답변을 참조하십시오!


8
개인적 null으로 "vanilla"JavaScript에서 s를 사용 하여 변수 또는 속성 값을 초기화합니다. 주어진 var 또는 prop이 존재하지만 "사용 가능한 값이 없음"이 있거나 "일부 실행 지점에서 값이 지워진 경우"에 대한 답을 얻을 수 있습니다. 그것은 단지 관습에 의한 것입니다. 여기에서 답변으로 볼 수 있듯이 TypeScript에서 가장 좋은 방법은 아닙니다. 당신의 생각에 감사합니다.
grasnal

25
심지어 초기화하지 않습니다 억제 "개체는 가능하다 '정의되지 않은'"TS 2.7.2에서 나를 위해
Tyguy7

1
예. 그러나 이러한 정의는 객체의 값을 변경합니다. 예를 들어 HTMLDivElement에는 가장 가까운 대상 및 기타 기본 요소 이벤트 및 속성이 없습니다.
Clarence

5
시작 상태의 실제 표현이 어떤 Javascript 객체 속성의 상태를 설명하려는 경우 어떻게해야 null합니까?
Timur Mamedov

1
!Kotlin 의 연산자와 매우 유사한 연산자를 사용할 수 있다는 점을 추가하면 이러한 검사를 훨씬 간결하게 할 수 있습니다.
Alvaro

600

당신이 표현이 아니라고 외부 수단에서 알고있는 경우 null또는 undefined, 당신은 null이 아닌 주장 연산자를 사용하여 !그 유형을 멀리 강요 :

// Error, some.expr may be null or undefined
let x = some.expr.thing;
// OK
let y = some.expr!.thing;

12
! - Non-null assertion operator운영자 에 대해 알려 주셔서 감사합니다 . 일이 아직 잘 문서화되지 않은 것 같습니다 ( https://github.com/Microsoft/TypeScript/issues/11494 ) 답변을 찾는 사람은이 http://stackoverflow.com/questions/38874928/operator-in-typescript를
after

9
이것은 또한 tsc v2.7.2에 영향을 미치지 않습니다
Tyguy7

6
@ThomasSauvajon !여기 의 연산자 는 C #에서 와 같은 작업을 수행 하지 않습니다? ! 유형 시스템 주장 일뿐입니다 . null또는 에서 속성을 읽으려고 할 때 프로그램이 중단되지 않습니다 undefined.
Ryan Cavanaugh

2
Ryan의 prodding에 추가 된 핸드북에서 : 구문은 postfix !: identifier!removes nulland undefinedtype에서identifier Ryan이 이미 말한 것입니다. 그러나이 방법도 도움이됩니다.
John Hatton

5
Typescript 3.2.2에서는 작동하지 않습니다. 제거 되었습니까?
Lars Nyström

25

나는 사용했다 :

if (object !== undefined) {
    // continue - error suppressed when used in this way.
}

또는 유형 강제를 사용할 수 있습니다.

const objectX = object as string

위의 해결 방법 중 하나를 선택하기 전에 원하는 아키텍처를 고려하고 더 큰 그림에 영향을 미치십시오.


57
어떤 이유로 든 내 TSC는 if 문이 여전히 정의되지 않은 것으로 간주한다는 것을 무시합니다 ...
Tyguy7

9
사용할 때 오류가 발생하지 않습니다if(object!==undefined) object.function();
Jérémy

하나는 이중 비교 사용할 수 nullundefined, 그리고 (그 두 가지 유형으로 사용하는 경우에만) 나쁜 방법이 아닙니다 - 이벤트 TSLint은 당신이 그것을 할 수 있습니다. 쓰기 대신 무언가를 정의 null !== someObject && undefined !== someObject할 수 있어 쉽게 확인할 수 있습니다.null != someObject
Marecky

15

OP의 질문에 대한 직접적인 대답은 아니지만 제 경우에는 다음과 같이 설정했습니다.

타이프 라이터 - v3.6.2
tslint -v5.20.0

그리고 다음 코드를 사용하여

const refToElement = useRef(null);

if (refToElement && refToElement.current) {
     refToElement.current.focus(); // Object is possibly 'null' (for refToElement.current)
}

해당 라인의 컴파일러를 억제하여 계속 진행했습니다. linter 오류가 아닌 컴파일러 오류이므로 // tslint:disable-next-line작동하지 않았습니다. 또한, 필요한 경우에만 문서에 따라,이, 드물게 사용되어야한다 -

const refToElement = useRef(null);

if (refToElement && refToElement.current) {
     // @ts-ignore: Object is possibly 'null'.
     refToElement.current.focus(); 
}

업데이트 :

Typescript 3.7에서는 선택적 체인을 사용 하여 위의 문제를 다음과 같이 해결할 수 있습니다.

refToElement?.current?.focus();

2
을 비활성화하는 것보다 훨씬 더 나은 해결책은 strictNullChecks주의를 기울여야합니다. 대부분의 경우 null 참조 오류가 발생하면 실제 두통이 발생할 수 있습니다.
Andy Braham

'never'유형에 'getBoundingClientRect'특성이 없습니다.
mqliutie

필자의 경우이 선택적 체인이 작동하지 않았습니다. const input = useRef<HTMLInputElement>(null);if (input && input.current) { input.current.value = ''; }트릭을했다.
티모

13

이 솔루션은 저에게 효과적이었습니다.

  • tsconfig.json으로 이동하여 "strictNullChecks"를 추가하십시오 .

여기에 이미지 설명을 입력하십시오


이것은 나를 위해 일했다. 예를 들어 subscribe 문에서 여전히 오류가 발생하지만 결과 변수를 인식하지 못하고 typescript는 .subscribe (result => this.result = result.json ());
Aarchie

'map'연산자를 사용해 보셨습니까? 구글 'rxjs / map'. 나는 기본적으로 :. Http.get (...). map (result => result.json ()). subscribe (result => {여기에 물건을 넣으십시오})
Mahesh Nepal

38
질문에 대답하지 않습니다. OP는 명시 적으로 'TS 컴파일러 검사를 비활성화하지 않고'
pvill

4
TypeScript를 사용하고 linter 오류를 제거하는 것이 당신에게 경고하는 것이 무엇입니까? as100 % 확실하다면 원하는 값을 캐스팅하는 것이 더 나은 옵션이라고 생각합니다 . 나는 MongoDB를하고 FindOneOrUpdate 반환 값의 경우를했고 나는이 때문에 스키마에 캐스팅했다 result.value로 선언 TSchema | undefined하고 난 이미 확인했습니다 result.ok전에
빈센트

12

유형이 절대로 null또는 이 아님을 알고 undefined있으면를 foo: Bar없이 선언해야 합니다 ?. ? Bar구문을 사용 하여 형식을 선언하면 잠재적으로 정의되지 않았을 수 있으므로 확인해야합니다.

다시 말해, 컴파일러는 요청한 내용을 정확하게 수행합니다. 선택 사항으로하려면 나중에 확인해야합니다.


1
"컴파일러가 요청한대로 정확하게 수행하고 있습니다."제 아이디어는 잘못되었습니다. 접근 방식을 조금 바꿔야합니다.
grasnal

필자의 경우 컴파일러는 객체를 이미 null로 확인했음을 알지 못했습니다. null을 확인하고 해당 getter를 호출하는 getter가 있습니다. 그래서 아니오, 그것은 내가 요청한 것을 정확하게하지 않습니다 (이것이 모든 것을 알아낼 것이라고 기대하는 것은 아닙니다).
CWagner

9

이것은 OP의 문제는 아니지만 Object is possibly 'null'우연히 null 유형으로 매개 변수를 선언했을 때 동일한 메시지가 나타납니다.

something: null;

null 값을 할당하는 대신 :

something: string = null;

2
이것이 실제 답변입니다. 실제 명시 적 null 검사를 수행해도 여전히 Object is possibly 'null'오류가 발생합니다. 이 대답은 그것을 해결합니다.
Ben Racicot 2016 년

5

옵션으로 타입 캐스팅을 사용할 수 있습니다. typescript 에서이 오류가 발생하면 일부 변수에 유형이 있거나 정의되지 않았 음을 의미합니다.

let a: string[] | undefined;

let b: number = a.length; // [ts] Object is possibly 'undefined'
let c: number = (a as string[]).length; // ok

a코드에 실제로 존재 하는지 확인하십시오 .



2

RxJS를위한 팁

나는 종종 type의 멤버 변수를 가질 Observable<string>것이며, ngOnInitAngular를 사용할 때까지 초기화하지 않을 것 입니다. 그런 다음 컴파일러는 '생성자에 확실히 할당되지 않았기 때문에 초기화되지 않은 것으로 가정합니다. 컴파일러는 결코 이해하지 못합니다 ngOnInit.

!오류를 피하기 위해 정의 에서 어설 션 연산자를 사용할 수 있습니다 .

favoriteColor!: Observable<string>;

초기화되지 않은 Observable은 '스트림을 제공해야하지만 null을 제공했습니다'와 같은 오류로 모든 종류의 런타임 문제를 일으킬 수 있습니다. 은 !당신이 경우 괜찮 확실히 이 같은 설정 될 것 알고 ngOnInit있지만 값이 약간 덜 결정 론적 방식으로 설정되는 경우가있을 수 있습니다.

그래서 때때로 사용하는 대안은 다음과 같습니다.

public loaded$: Observable<boolean> = uninitialized('loaded');

어디 uninitialized선가 세계적으로 정의된다 :

export const uninitialized = (name: string) => throwError(name + ' not initialized');

그런 다음이 스트림을 정의하지 않고 사용하면 즉시 런타임 오류가 발생합니다.


나는 어디서나 이것을하는 것을 권장하지 않지만, 때때로 이것을 할 것입니다-특히 외부에서 설정된 @Input 매개 변수에 의존하는 경우
Simon_Weaver

2

ReactJS에서 변수가 null인지 여부를 생성자에서 확인합니다. 변수가 예외처럼 취급되고 예외를 적절하게 관리합니다. 변수가 null이 아닌 경우 코드는 계속 수행되고 해당 시점 이후에는 컴파일러가 더 이상 불평하지 않습니다.

private variable1: any;
private variable2: any;

constructor(props: IProps) {
    super(props);

    // i.e. here I am trying to access an HTML element
    // which might be null if there is a typo in the name
    this.variable1 = document.querySelector('element1');
    this.variable2 = document.querySelector('element2');

    // check if objects are null
    if(!this.variable1 || !this.variable2) {
        // Manage the 'exception', show the user a message, etc.
    } else {
        // Interpreter should not complain from this point on
        // in any part of the file
        this.variable1.disabled = true; // i.e. this line should not show the error
    }

1

상태를 설정하고 사용할 때 React를 사용 하여이 문제에 부딪 쳤습니다 map.

이 경우 API 가져 오기 호출을 수행했으며 응답 값을 알 수 없지만 "응답"값 있어야합니다. 나는 이것을 위해 커스텀 타입을 사용했지만 그 값은 일 수 있기 때문에 null어쨌든 TS 오류가 발생했다. 유형을 null수정해도 문제가 해결되지 않습니다. 또는 당신은 사용할 수 default parameter value있지만 이것은 내 경우에 지저분했습니다.

삼항 연산자를 사용하여 응답이 비어있는 경우 기본값을 제공하여 극복했습니다.

this.setState({ record: (response.Answer) ? response.Answer : [{ default: 'default' }] });

0

typescript에서 다음을 수행하여 다음을 억제 할 수 있습니다 error.

let subString?: string;

subString > !null; -null 앞에 추가 된 느낌표에 유의하십시오.


0

다음과 같이 객체를 호출하십시오.

(<any>Object).dosomething

이 오류는를 사용하여 옵션으로 선언했기 때문에 발생했습니다 ?. 이제 Typescript는 엄격한 검사를 수행하며 undefined. 따라서 (<any>yourObject)여기에서 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.