TypeScript'te nesne değişmezinde tür tanımı


346

TypeScript sınıflarında özellikler için tür bildirmek mümkündür, örneğin:

class className {
  property: string;
};

Bir nesne değişmezindeki bir özelliğin türünü nasıl bildiririm?

Aşağıdaki kodu denedim ama derlemiyor:

var obj = {
  property: string;
};

Aşağıdaki hatayı alıyorum:

'Dize' adı geçerli kapsamda mevcut değil

Yanlış bir şey mi yapıyorum yoksa bu bir hata mı?

Yanıtlar:


424

Oldukça yakınsın, sadece yerine =bir :. Nesne türü değişmez değeri (bkz. Bölüm 3.5.3'e bakın) veya bir arabirim kullanabilirsiniz. Nesne türü değişmezi kullanmak, sahip olduğunuza yakındır:

var obj: { property: string; } = { property: "foo" };

Ancak bir arayüz de kullanabilirsiniz

interface MyObjLayout {
    property: string;
}

var obj: MyObjLayout = { property: "foo" };

14
@Rick Love'ın döküm operatörü ile DRY (Kendini Tekrar Etme) seçeneği mucho neater gibi görünüyor. Sadece yorum, aşağı değil ...
spechter

Bunun bir süre önce yanıtlandığını biliyorum, ama sınıfın yöntemleri olduğu kadar özellikleri olduğunda sorunların ortaya çıkabileceği varsayımlarında yanlış mıyım? Sınıf başlatılmadığından ve yalnızca özellikler atadığımızdan, sınıfta bir yöntem çağrıldığında boş bir özel duruma neden olur. Temel olarak, oluşturduğumuz nesne, sınıfını yalnızca atadığımız için sınıf olarak hareket eder, ancak aslında bu sınıfın bir örneği değildir. Yani sınıfı 'yeni' anahtar kelimeyle oluşturmamız gerekiyor. Ve sonra yeni kareye () {prop: 1} gibi bir şey yapamadığımız için 1. kareye geri dönüyoruz; TS'de örneğin C # 'daki gibi.
DeuxAlpha

@DeuxAlpha Bu, yöntemleri bulunamayan bir arayüze atamaktadır . Böyle bir sınıfa atayabileceğine inanmıyorum.
Mog0

spec bağlantısı iyi olurdu :)
ahong

@DeuxAlpha bu bir sınıf nesnesi değil, bir nesne hazır bilgisi oluşturuyor. Ayrıca bir arayüzde yöntemler olabilir. Arayüzünüz bir yöntem tanımlıyorsa, nesne değişmez değeri de bunu tanımlamalıdır - boş olmaz. Nesne hazır bilgisi, arabirimin tanımladığı her şeyi yerine getirmelidir; aksi takdirde tür sistemi bir hata gösterir.
Rick Love

291

Güncelleme 2019-05-15 (Alternatif Olarak Geliştirilmiş Kod Modeli)

Uzun yıllar kullanıldıktan constve daha işlevsel kodlardan yararlandıktan sonra, çoğu durumda aşağıdakileri kullanmamanızı tavsiye ederim. (Nesneleri oluştururken, yazı sistemini türler çıkarmasına izin vermek yerine belirli bir türe zorlamak genellikle bir şeyin yanlış olduğunun bir göstergesidir).

Bunun yerine constdeğişkenleri olabildiğince kullanmanızı ve ardından nesneyi son adım olarak oluşturmanızı öneririm :

const id = GetId();
const hasStarted = true;
...
const hasFinished = false;
...
return {hasStarted, hasFinished, id};
  • Bu, açıkça yazmaya gerek olmadan her şeyi düzgün bir şekilde yazacaktır.
  • Alan adlarının yeniden yazılmasına gerek yoktur.
  • Bu benim deneyim en temiz kodu yol açar.
  • Bu, derleyicinin daha fazla durum doğrulaması sağlamasına izin verir (örneğin, birden çok konuma geri dönerseniz, derleyici her zaman aynı tür nesnenin döndürülmesini sağlar - bu, her bir konumdaki tüm dönüş değerini bildirmenizi sağlar - mükemmel bir netlik sağlar. bu değerin niyeti).

İlave 2020-02-26

Tembel olarak başlatılabileceğiniz bir türe gerçekten ihtiyacınız varsa: Boş değerli bir birleşim türü (null veya Tür) olduğunu işaretleyin. Tip sistemi, önce bir değere sahip olduğundan emin olmadan onu kullanmanızı engeller.

İçinde tsconfig.json , katı boş denetimleri etkinleştirdiğinizden emin olun:

"strictNullChecks": true

Ardından bu deseni kullanın ve tür sisteminin sizi yanlışlıkla boş / tanımsız erişimden korumasına izin verin:



const state = {
    instance: null as null | ApiService,
    // OR
    // instance: undefined as undefined | ApiService,

};

const useApi = () => {
    // If I try to use it here, the type system requires a safe way to access it

    // Simple lazy-initialization 
    const api = state?.instance ?? (state.instance = new ApiService());
    api.fun();

    // Also here are some ways to only access it if it has value:

    // The 'right' way: Typescript 3.7 required
    state.instance?.fun();

    // Or the old way: If you are stuck before Typescript 3.7
    state.instance && state.instance.fun();

    // Or the long winded way because the above just feels weird
    if (state.instance) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans way
    if (state.instance != null) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans 
    // AND I was told to always use triple === in javascript even with null checks way
    if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); }
};

class ApiService {
    fun() {
        // Do something useful here
    }
}

Vakaların% 99'unda aşağıdakileri yapmayın:

Güncelleme 2016-02-10 - TSX ile İlgili (Teşekkürler @Josh)

asTSX için operatörü kullanın .

var obj = {
    property: null as string
};

Daha uzun bir örnek:

var call = {
    hasStarted: null as boolean,
    hasFinished: null as boolean,
    id: null as number,
};

Orijinal Yanıt

Bu özlü yapmak için döküm operatörünü kullanın (istenen türe boş döküm yaparak).

var obj = {
    property: <string> null
};

Daha uzun bir örnek:

var call = {
    hasStarted: <boolean> null,
    hasFinished: <boolean> null,
    id: <number> null,
};

Bu, iki parçaya sahip olmaktan çok daha iyidir (biri bildirmek için, diğeri varsayılanları bildirmek için):

var callVerbose: {
    hasStarted: boolean;
    hasFinished: boolean;
    id: number;
} = {
    hasStarted: null,
    hasFinished: null,
    id: null,
};

10
TSX (JSX ile TS) kullanıyorsanız, açılı ayraç adlandırma kullanamazsınız, bu nedenle bu satırlar property: null as stringönemli farkın asoperatör olduğu gibi bir şey haline gelir .
Josh

2
@RickLove Bu aslında nesne değişkeninin türünü kısıtlıyor mu, yoksa bu atanan türleri belirtmenin bir yolu mu? Başka bir deyişle, callikinci örneğinizdeki değişkene atadıktan sonra, değişkene tamamen farklı bir tür atayabilir misiniz?
Daniel Griscom

3
Bu cevap olmalı
Drew R

4
çalışmıyor. Error:(33, 15) TS2352:Type 'null' cannot be converted to type 'string'.
slayt gösterisi2

2
Bu sadece dilin bir özelliğini kötüye kullanıyor mu yoksa bu aslında yasal mı? Resmi belgelere daha fazla okumak için bağlantı sağlayabilir misiniz? Teşekkürler!
Qwerty

31

Kimsenin bundan bahsetmediğine şaşırdım, ancak sadece tür çiftlerini ObjectLiteralkabul eden bir arabirim oluşturabilirsiniz :key: valuestring: any

interface ObjectLiteral {
  [key: string]: any;
}

O zaman şöyle kullanırsınız:

let data: ObjectLiteral = {
  hello: "world",
  goodbye: 1,
  // ...
};

Ek bir avantaj, bu arayüzü istediğiniz kadar, istediğiniz sayıda nesnede tekrar kullanabilmenizdir.

İyi şanslar.


3
Bu kötü bir fikir, yazı sistemini değersiz kılıyor. Daktilo yazısının türü, yazı sisteminin hataları önlemeye ve takımlamada daha iyi otomatik tamamlama işlevselliği sağlamaya yardımcı olmasını sağlamaktır - bu temelde dakikanın tüm faydalarını devre dışı bırakır. Yukarıdaki örnekte herhangi bir arayüz kullanmamak daha iyi olur.
Rick Love

1
@RickLove Kesinlikle katılmıyorum. Bu, birkaç özellik isteğe bağlı olduğunda son derece kullanışlıdır, ancak yine de içindeki tüm türleri açıkça tanımlamak istiyoruz (örneğin, bir işlev için bağımsız değişkenler içeren). Bu sadece sözdizimsel şeker olarak görülebilir ve kelimenin tam anlamıyla Arayüzlerin özellikleri için bir yayma operatörü gibi çalışır .
CPHPython

@CPHPython neden isteğe bağlı parametreleri sadece belirli türleriyle belirtmiyorsunuz? Bunun mantıklı olacağı tek zaman, adların kod zamanında bilinmemesidir (yani bir veritabanından veya harici kaynaktan geliyorsa). Ayrıca karmaşık argüman kombinasyonları için sendika türleri harika çalışıyor. Belirli isimlere kod yazıyorsanız, mümkünse bunlar tanımlanmalıdır. Sadece mantığı etkilemeyen verilerse, elbette onu tip sisteminden uzak tutun.
Rick Love

1
@RickLove "adlar kod zamanında bilinmemektedir" -> bu iyi ve pratik bir örnektir, bu anahtar türlerinin değerleri bilinir ve hepsi aynıdır (örneğin dize ). Yalnızca [key: string]parçanın kullanımını savunduğumu, değerin tür tanımı olarak herhangi bir parçayı değil, gerçekten yararlılığı dışarıda bırakacağımı aklınızda bulundurun.
CPHPython

1
Başka türlere değil, dize ve sayıların eklenmesine izin vermek istersem nasıl olur?
DonkeyBanana

14

Bir tür ek açıklaması yazmaya çalışıyorsanız, söz dizimi:

var x: { property: string; } = ...;

Bir nesne hazır bilgisi yazmaya çalışıyorsanız, söz dizimi:

var x = { property: 'hello' };

Kodunuz değer konumunda bir tür adı kullanmaya çalışıyor.


10
Sizin var x: { property: string; } = ...;bir alay! Üç nokta için sözdiziminin geçerli bir sözdizimi olmasını umuyordum var x: { property: string; } = { property: 'hello' };.
Jason Kleban

10

TypeScript'te nesne bildiriyorsak, aşağıdaki sözdizimini kullanırız:

[access modifier] variable name : { /* structure of object */ }

Örneğin:

private Object:{ Key1: string, Key2: number }

7

Bir üzere typings eklemek çalışıyorsanız Bozunmamış bir işleve argümanlar, örneğin, nesnesi değişmez, sözdizimi:

function foo({ bar, baz }: { bar: boolean, baz: string }) {
  // ...
}

foo({ bar: true, baz: 'lorem ipsum' });

5

Mülkleriniz aynı türe sahipse, önceden tanımlanmış yardımcı program türünü kullanabilirsiniz Record:

type Keys = "property" | "property2"

var obj: Record<Keys, string> = {
  property: "my first prop",
  property2: "my second prop",
};

Elbette daha ileri gidebilir ve mülk değerleriniz için özel bir tür tanımlayabilirsiniz:

type Keys = "property" | "property2"
type Value = "my prop" | "my other allowed prop"

var obj: Record<Keys, Value> = {
  property: "my prop",
  property2: "my second prop", // TS Error: Type '"my second prop"' is not assignable to type 'Value'.
};

2
Tam olarak ihtiyacım olan şey. Teşekkürler! Kazanmak için daktilo!
Audacitus

Burada letyerine de kullanırım var.
Fwd079

3
// Use ..

const Per = {
  name: 'HAMZA',
  age: 20,
  coords: {
    tele: '09',
    lan: '190'
  },
  setAge(age: Number): void {
    this.age = age;
  },
  getAge(): Number {
    return age;
  }
};
const { age, name }: { age: Number; name: String } = Per;
const {
  coords: { tele, lan }
}: { coords: { tele: String; lan: String } } = Per;

console.log(Per.getAge());

3
Hey ve SO'ya hoş geldiniz! Cevabınızı hiç genişletebilir misiniz, bunun nasıl / neden çalıştığını açıklamak yardımcı olacaktır.
parti ringi

1

Kodunuzda:

var obj = {
  myProp: string;
};

Aslında bir nesne hazır bilgisi oluşturuyor ve değişken dizeyi myProp özelliğine ataıyorsunuz. Çok kötü uygulama olmasına rağmen bu aslında geçerli TS kodu olacaktır (bunu kullanmayın!):

var string = 'A string';

var obj = {
  property: string
};

Ancak, istediğiniz nesne değişmezinin yazılmasıdır. Bu çeşitli yollarla gerçekleştirilebilir:

Arayüz:

interface myObj {
    property: string;
}

var obj: myObj = { property: "My string" };

Özel tür:

type myObjType = {
    property: string
};

var obj: myObjType = { property: "My string" };

Oyuncular:

var obj = {
    myString: <string> 'hi',
    myNumber: <number> 132,
};

Nesne türü değişmez değeri:

var obj: { property: string; } = { property: "Mystring" };
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.