「エラーTS2533:オブジェクトはおそらく「null」または「未定義」です」を抑制する方法は?


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

この機能は「厳格なnullチェック」と呼ばれ、オフにして、--strictNullChecksコンパイラフラグが設定されていないことを確認します。

ただし、の存在はThe Billion Dollar Mistakeと説明されnullているため、TypeScriptなどの言語が修正を導入するのを見るのはエキサイティングです。オンにしておくことを強くお勧めします。

これを修正する1つの方法は、たとえば値を前もって初期化するなどして、値が決して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、「バニラ」JavaScriptでs を使用して、変数またはプロパティ値を初期化しています。これは、与えられたvarまたはpropが存在するが、「まだ使用可能な値がない」または「実行のある時点で値がクリアされた」場合、私に直接的な答えを与えます。慣例によるものです。TypeScriptでは、ここでの回答からわかるように、これは最善のアプローチではない可能性があります。どうもありがとうございました。
— grasnal

25
初期化でさえ、TS 2.7.2の「オブジェクトはおそらく「未定義」である」を抑制しません
— Tyguy7

1
はい。ただし、これらの定義はオブジェクトの値を変更します。たとえば、HTMLDivElementには最も近いターゲットやその他の基本的な要素のイベントやプロパティはありません。
— クラレンス

5
開始状態の真の表現があるJavascriptオブジェクトプロパティの状態を記述しようとしている場合はどうでしょうnullか。
— Timur Mamedov

1
加えて!、これらのチェックをより簡潔にすることができるKotlinのものと非常によく似た演算子が利用可能です
— Alvaro

598

外部の手段から、式がnullor 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-object-method
— grasnal

9
これは私にとってtsc v2.7.2にも影響しません
— Tyguy7

6
@ThomasSauvajon !オペレータんここにいないのと同じことを行う?C#がありませんで!これはタイプシステムアサーションにすぎません。nullまたはからプロパティを読み取ろうとしたときにプログラムがクラッシュすることはありませんundefined。
— Ryan Cavanaugh

2
ハンドブックから、ライアンのプロディングで追加: 構文はpostfix !:からidentifier!削除nullしundefined、identifier これのタイプからこれはライアンがすでに言ったことですが、私もこの方法が役立つと思います。
— John Hatton

5
これはTypescript 3.2.2では機能しません。削除されましたか?
— LarsNyström19年

25

私が使用した:

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

または、型強制を使用することもできます。

const objectX = object as string

ただし、上記の回避策のいずれかを選択する前に、目的のアーキテクチャを検討してください。それが全体像に影響を与えます。


57
何らかの理由で、私のTSCはifステートメントを無視しますが、それでも未定義であると見なします...
— Tyguy7

9
私が使用したときに、私のエラーがsupressedされていませんif(object!==undefined) object.function();
— ジェレミー

nullandとの二重比較を使用することもできます。undefinedこれは悪い習慣ではありません(これらの2つのタイプを使用する場合のみ)-イベントTSLintを使用すると、これを実行できます。何かを定義するかどうかを簡単にチェックnull !== someObject && undefined !== someObjectできるのは、書く代わりに次のように使用できるためですnull != someObject
— Marecky

14

OPの質問への直接の回答ではありませんが、私の場合、私は次の設定をしました-

v3.6.2
Typescript - tslint-v5.20.0

そして、次のコードを使用して

const refToElement = useRef(null);

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

その行のコンパイラーを抑制して先に進みました。これはコンパイラエラーであり、リンターエラーで// 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参照エラーが必要になるため、実際の頭痛の種になる可能性があります。
— アンディブラハム

プロパティ「getBoundingClientRect」はタイプ「never」には存在しません。
— 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

「マップ」演算子を使用してみましたか?Google 'rxjs / map'。私は基本的に:。Http.get(...)。map(result => result.json())。subscribe(result => {do your stuff here})
— Mahesh Nepal

38
質問に答えません。OPは「TSコンパイラチェックを無効にしないで」と明言しました
— pvill

4
TypeScriptを使用してリンターエラーを削除する目的は、警告を出すことですか?asあなたが100%確信している場合は、望ましい値をキャストすることをお勧めします。私はMongoDBのとFindOneOrUpdateの戻り値を持つケースを持って、私はので、スキーマにキャストしなければならなかったresult.valueとして宣言されているTSchema | undefinedと私はすでにに確認してきたresult.ok前に
— ヴィンセント

12

タイプがnullor undefinedにならないことがわかっている場合は、foo: Barなしで宣言する必要があり?ます。? Bar構文を使用して型を宣言すると、型が未定義になる可能性があるため、確認する必要があります。

言い換えると、コンパイラーは、ユーザーが求めていることを正確に実行しています。オプションにする場合は、後で確認する必要があります。


1
「コンパイラはあなたが求めていることを正確に実行している」ので、私の考えは間違っています。アプローチを少し変える必要があります。
— grasnal

私の場合、コンパイラはオブジェクトがnullかどうかをすでにチェックしていることに気づきませんでした。nullをチェックするゲッターがあり、そのゲッターを呼び出します。だから、いいえ、それは私がそれを求めたとおりに行っているわけではありません(すべてを理解することを期待していると言っているわけではありません)。
— CWagner

9

これはOPの問題ではありませんが、Object is possibly 'null'誤ってパラメーターをnull型として宣言したときにも同じメッセージが表示されました。

something: null;

nullの値を割り当てる代わりに:

something: string = null;

2
これが実際の答えです。実際の明示的なnullチェックを実行してもまだObject is possibly 'null'エラーが発生する場合はイライラします。この答えはそれを解決します。
— Ben Racicot

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コードに実際に存在することを確認してください。


3

TypeScript 3.7(https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)以降では?.、属性にアクセスする(またはメソッドを呼び出す)ときに演算子を使用して未定義にすることができます)nullまたは未定義のオブジェクト:

inputEl?.current?.focus(); // skips the call when inputEl or inputEl.current is null or undefined

オプションのプロパティアクセス演算子は?.です。
— アベンチュリン

2

RxJSのヒント

多くの場合、タイプのメンバー変数がありObservable<string>、ngOnInit(Angularを使用して)初めてそれを初期化します。コンパイラーは、「コンストラクターで明確に割り当てられていない」ため、初期化されていないと見なし、コンパイラーはそれを理解しませんngOnInit。

!エラーを回避するために、定義でアサーション演算子を使用できます。

favoriteColor!: Observable<string>;

初期化されていないオブザーバブルは、「ストリームを提供する必要があるが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である場合は例外のように扱い、例外を適切に管理します。変数が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フェッチ呼び出しを行っていて、応答の値は不明でしたが、「Answer」という値が必要です。これにはカスタムタイプを使用しましたが、値がである可能性があるため、nullとにかくTSエラーが発生しました。タイプを許可nullしても問題は解決しません。または、を使用することもできますがdefault parameter value、これは私の場合は面倒でした。

3項演算子を使用するだけで応答が空の場合にデフォルト値を提供することで、これを克服しました。

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.