“Hata TS2533: Nesne muhtemelen 'null' veya 'undefined'” nasıl bastırılır?


226

Bende type:

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

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

  maxVisibleListItems?: number
}

Global bir modül bilge değişkeni beyan ederim:

var $protected : tSelectProtected = {};

function1()Kapsamda uygun bir değer ataıyorum:

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

Daha sonra function2()kapsamda arıyorum:

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

TypeScript hatası alıyorum:

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

if ($protected.listEle) {$protected.listEle}Derleyiciyi sakinleştirmek için açık kontrol yapabileceğimi biliyorum, ancak bu önemsiz vakaların çoğu için çok kullanışlı görünmüyor.

TS derleyici kontrolleri devre dışı bırakılmadan bu durum nasıl ele alınmalı veya nasıl ele alınmalıdır?

Yanıtlar:


99

--strictNullChecksDerleyici bayrağının ayarlanmadığından emin olmak için bu özelliğe "katı boş denetimler" denir .

Ancak, varlığı nullvardır tanımlanmıştır olarak Milyar Dolar Mistake , nedenle böyle typescript bir düzeltme tanıtan gibi dilleri görmek heyecan verici. Açık tutmanızı şiddetle tavsiye ederim.

Bunu düzeltmenin bir yolu, değerlerin hiçbir zaman olmamasını nullveya undefinedörneğin önyükleme yaparak olmasını sağlamaktır :

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

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

Yine de Ryan Cavanaugh'un alternatif bir seçenek için cevabına bakın!


8
Şahsen ben nulldeğişkenleri veya özellik değerlerini başlatmak için "vanilya" JavaScript s kullanın . Bu, var veya prop verildiğinde bana doğrudan yanıt veriyor ancak henüz "kullanılabilir değeri yok" veya "değer bir yürütme noktasında temizlendi". Sadece kongre ile. Buradaki cevaplarla görebildiğim için bu, TypeScript'te en iyi yaklaşım olmayabilir. Düşünceleriniz için teşekkür ederim.
grasnal

25
Başlatma bile TS 2.7.2'de benim için "Nesne büyük olasılıkla" tanımsız "ı
engellemiyor

1
Evet, ancak bu tanımlar nesnelerin değerlerini değiştirir, örneğin HTMLDivElement en yakın hedef ve diğer temel öğe olaylarına ve özelliklerine sahip değildir.
Clarence

5
Başlangıç ​​durumunun gerçek temsili olan bazı Javascript Object özelliğinin durumunu açıklamaya çalışıyorsanız ne olur null?
Timur Mamedov

1
!Bu kontrolleri çok daha özlü hale getirmenizi sağlayan Kotlin'deki operatörlere çok benzer bir operatör olduğunu ekleyerek
Alvaro

600

Harici yollardan bir ifadenin olmadığını nullveya olmadığını belirtirseniz undefined, !bu türleri zorlamak için null olmayan onaylama işlecini kullanabilirsiniz:

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

12
! - Non-null assertion operatorOperatör hakkında bilgi verdiğiniz için teşekkürler . Görünüşe göre bu şey henüz iyi belgelenmemiş ( https://github.com/Microsoft/TypeScript/issues/11494 ), bu yüzden cevap arayan herkes bu http://stackoverflow.com/questions/38874928/operator-in-typescript -after-object-method
grasnal

9
bu da benim için tsc v2.7.2
Tyguy7

6
@ThomasSauvajon !operatör yok burada değil aynı şeyi yapmak ?C # yapar içinde! Sadece bir tür sistem iddiasıdır; nullveya öğesinden bir özellik okumaya çalıştığınızda programınızın çökmemesine neden olmaz undefined.
Ryan Cavanaugh

2
El kitabından, Ryan'ın prodding'e eklendi: Sözdizimi postfix !: identifier!kaldırır nullve undefinedtüründenidentifier Ryan'ın zaten söylediği şey budur, ancak bu yolu da yararlı buluyorum.
John Hatton

6
Bu, Typcript 3.2.2'de çalışmaz. Kaldırıldı mı?
Lars Nyström

25

Kullandım:

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

Alternatif olarak, zorlama türü kullanabilirsiniz:

const objectX = object as string

Bununla birlikte, yukarıdaki geçici çözümlerden birini seçmeden önce, lütfen hedeflediğiniz mimariyi ve daha büyük resmin etkisini göz önünde bulundurun.


57
nedense benim TSC eğer ifade, hala muhtemelen tanımsız olduğunu düşünüyor görmezden ...
Tyguy7

9
kullandığımda hatam bastırılmıyorif(object!==undefined) object.function();
Jérémy

Bir de çift karşılaştırmayı kullanabilirsiniz nullve undefinedve (bu iki tip kullanarak yalnızca) kötü bir uygulama değil - Olay TSLint bunu sağlayacaktır. Bir şey tanımlanıp tanımlanmadığını kontrol null !== someObject && undefined !== someObjectetmeyi kolaylaştırır çünkü yazmak yerine sadece kullanabilirsiniznull != someObject
Marecky

15

OP'nin sorusuna doğrudan bir cevap değil, ama benim durumumda, aşağıdaki kurulumu yaptım -

Typescript - v3.6.2
tslint -v5.20.0

Ve aşağıdaki kodu kullanarak

const refToElement = useRef(null);

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

Bu satır için derleyiciyi bastırarak devam ettim. Linter hatası değil bir derleyici hatası olmadığından, // tslint:disable-next-lineişe yaramadığını unutmayın. Ayrıca, belgelere göre, bu sadece gerektiğinde nadiren kullanılmalıdır -

const refToElement = useRef(null);

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

GÜNCELLEME :

Typescript 3.7 ile, yukarıdaki sorunu çözmek için isteğe bağlı zincirleme kullanabilirsiniz -

refToElement?.current?.focus();

2
Devre dışı bırakmaktan çok daha iyi bir çözüm strictNullChecks, dikkatli kullanılmalıdır, çoğu zaman null referans hatasını istersiniz çünkü yolda gerçek baş ağrılarına neden olabilir.
Andy Braham

'GetBoundingClientRect' özelliği 'never' türünde mevcut değil.
mqliutie

Benim durumumda bu isteğe bağlı zincirleme işe yaramadı. const input = useRef<HTMLInputElement>(null);ve if (input && input.current) { input.current.value = ''; }hile yaptı.
Timo

13

Bu çözüm benim için çalıştı:

  • tsconfig.json adresine gidin ve "strictNullChecks" ifadesini ekleyin : false

resim açıklamasını buraya girin


Bu benim için de işe yaradı. Yine de, örneğin abone deyimlerinde hata vermesine rağmen, sonuç değişkenini tanımıyor olsa da, typescript .subscribe (sonuç => this.result = sonuç.json ());
Aarchie

'Harita' operatörünü kullanmayı denediniz mi? Google 'rxjs / harita'. Temelde: Http.get (...). Harita (sonuç => sonuç.json ()). Abone olun (sonuç => {işinizi burada yapın})
Mahesh Nepal

38
soruyu cevaplamıyor. OP açıkça şunları söyledi: 'TS derleyici kontrollerini devre dışı bırakmadan'
pvill

4
TypeScript kullanmanın ve linter hatasının kaldırılmasının amacı sizi uyarmayı amaçlıyor mu? asEğer daha iyi bir seçenek % 100 emin eğer ile istenen değeri döküm olduğunu düşünüyorum . Ben MongoDB ve FindOneOrUpdate dönüş değeri ile durum var ve ben çünkü Şeması için döküm vardı result.valueolarak ilan edilir TSchema | undefinedve zaten kontrol ettik result.okönce
Vincent

12

Eğer tipin asla olmayacağını biliyorsanız nullya undefinedda foo: Barolmadan, ilan etmelisiniz ?. ? BarSözdizimi ile bir tür bildirilmesi, potansiyel olarak tanımlanamayacağı anlamına gelir, bu da kontrol etmeniz gereken bir şeydir.

Başka bir deyişle, derleyici tam olarak sorduğunuz şeyi yapıyor. İsteğe bağlı olmasını istiyorsanız, daha sonra kontrol etmeniz gerekir.


1
"derleyici tam olarak sorduğunuz şeyi yapıyor" bu yüzden fikrim yanlış, teşekkürler. Yaklaşımı biraz değiştirmem gerek.
grasnal

Benim durumumda derleyici nesneyi zaten null için kontrol ettiğimi fark etmedi. Boş olup olmadığını kontrol eden bir alıcı var ve o alıcı çağırır. Yani hayır, tam olarak sorduğum şeyi yapmıyor (her şeyi çözmesini beklediğim anlamına gelmiyor).
CWagner

9

Bu OP sorunu değil, ama Object is possibly 'null'yanlışlıkla null türü olarak bir parametre bildirmişti aynı mesajı aldım :

something: null;

null değerini atamak yerine:

something: string = null;

2
Asıl cevap bu. Gerçek bir açık null denetim yaptığınızda sinir bozucu ve yine de Object is possibly 'null'hata alıyorum. Bu cevap bunu çözer.
Ben Racicot

5

Seçenek olarak, bir tür döküm kullanabilirsiniz. Herhangi bir değişkenin türü olduğu veya tanımsız olduğu anlamına gelen typescript'ten bu hatayla karşılaşırsanız:

let a: string[] | undefined;

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

aKodunuzda gerçekten var olduğundan emin olun .



2

RxJS için tavsiye

Sık sık üye değişkenlerim olur Observable<string>ve ngOnInit(Açısal kullanarak) kadar başlatır olmaz . Derleyici daha sonra 'kesinlikle kurucuya atanmamış' olduğundan başlatılmamış olduğunu varsayar ve derleyici asla anlamayacaktır ngOnInit.

!Hatayı önlemek için tanımdaki onaylama işlecini kullanabilirsiniz :

favoriteColor!: Observable<string>;

Başlatılmamış bir gözlemlenebilir, 'bir akış sağlamalısınız ancak null sağladınız' gibi hatalarla her türlü çalışma zamanı ağrısına neden olabilir. !Eğer varsa gayet kesinlikle bu gibi bir şey ayarlanabilir olacak biliyorum ngOnInit, ama değer, başka daha az deterministik bir şekilde ayarlanır durumlar olabilir.

Yani bazen kullanacağım bir alternatif:

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

Nerede uninitializedbir yere global olarak tanımlanır:

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

Bu akışı tanımlanmadan kullanırsanız, hemen bir çalışma zamanı hatası atar.


Her yerde bunu tavsiye etmiyoruz, ama bazen yapacağım - dışarıdan set @Input parametrelerine dayanarak özellikle
Simon_Weaver

2

ReactJS'de, yapıcıda değişkenlerin null olup olmadığını kontrol ederim, eğer bunlar bir istisna gibi davranır ve istisnayı uygun şekilde yönetirim. Değişkenler null değilse, kod devam eder ve derleyici bundan sonra şikayet etmez:

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

Durum ayarlarken ve kullanırken bunu React ile çalıştırdım map.

Bu durumda bir API getirme çağrısı yapıyordum ve yanıtın değeri bilinmiyordu, ama bir "Cevap" değerine sahip olmalı . Bunun için özel bir tür kullandım, ancak değer olabileceğinden null, yine de bir TS hatası aldım. Türün olmasına izin verilmesi nullsorunu gidermez; alternatif olarak bir kullanabilirsiniz default parameter value, ama bu benim durumum için dağınık oldu.

Sadece üçlü bir işleç kullanarak yanıtın boş olması durumunda varsayılan bir değer sağlayarak üstesinden geldim:

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

0

Daktiloda bastırmak için aşağıdakileri yapabilirsiniz error:

let subString?: string;

subString > !null; - Boşluktan önce eklenen ünlem işaretini not edin.


0

Nesneyi şöyle çağırmayı deneyin:

(<any>Object).dosomething

Bu hata, bunları isteğe bağlı kullanarak bildirdiğiniz için geldi ?. Şimdi Typescript sıkı kontrol yapıyor ve olabilecek herhangi bir şey yapmaya izin vermiyor undefined. Bu nedenle, (<any>yourObject)burada kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.