Typescript: Mengakses properti dalam gabungan tipe objek gagal untuk properti yang tidak ditentukan pada semua anggota serikat

Dibuat pada 10 Des 2016  ·  12Komentar  ·  Sumber: microsoft/TypeScript

Versi TypeScript: 2.1.1

Kode

type A = { a: string; } 
type B = { b: string; }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // use AorB.a
}

Perilaku yang diharapkan:
Kode dikompilasi tanpa kesalahan. Meskipun a tidak (harus) ada di semua konstituen serikat, fakta bahwa itu ada di beberapa harus memungkinkan saya untuk memeriksa .a dan menggunakannya jika ada.

Perilaku sebenarnya:
Ketikan keluhan: "Properti a tidak ada di tipe AorB ... Properti a tidak ada di tipe B."

Question

Komentar yang paling membantu

saya menemukan solusi di buku:

interface A { x:  number;} 
interface B { y:  string;}
function doStuff ( q: A | B ) {
  if ( 'x'  in q) {
    //  if type A...
  }
  else {
    // if type B...
  }
}

Kutipan Dari: Basarat Ali Syed. “TypeScript Deep Dive.” Apple Books.

properti pada objek dan dapat digunakan sebagai pelindung tipe, dan TypeScript dapat mengetahui tipe yang Anda gunakan.

Semua 12 komentar

Dokter mengatakan:

Agar kode yang sama berfungsi, kita perlu menggunakan pernyataan tipe:

let pet = getSmallPet();

if ((<Fish>pet).swim) {
    (<Fish>pet).swim();
}
else {
    (<Bird>pet).fly();
}

http://www.typescriptlang.org/docs/handbook/advanced-types.html

Kemudian dalam sampel Anda:

if ((<A>AorB).a) {
    // use AorB.a
}

Masalahnya di sini adalah karena B tidak mendeklarasikan properti a , mungkin pada saat run-time memiliki properti a dari jenis yang mungkin (karena Anda dapat menetapkan objek dengan set properti apa pun menjadi B selama ia memiliki properti tipe string b ). Anda dapat membuatnya bekerja secara eksplisit dengan mendeklarasikan properti a: undefined di B (dengan demikian memastikan bahwa B tidak akan memiliki properti a acak):

type A = { a: string; } 
type B = { b: string; a: undefined }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // Ok
}

Masuk akal. Otak kentut.

Jika Anda menentukan a: undefined pada tipe B, Anda harus menyetelnya ke undefined saat Anda membuat / meneruskan variabel.
Untuk menyiasatinya, Anda dapat mendeklarasikan a sebagai a?: undefined , dan skrip akan senang jika Anda menghilangkannya.

Jika saya memahami komentar dengan benar, ini seharusnya berfungsi (tetapi melempar; diuji di taman bermain): Apakah ini bug atau tidak? 🤔

type LinkProps = {
    to: string;
    onClick?: undefined;
    // Link specific props:
    target: string;
}

type ButtonProps = {
    to?: undefined;
    onClick: Function;
    // Button specific props:
    disabled: boolean;
}

type ActionProps = LinkProps | ButtonProps;

const Action = (props: ActionProps) =>
    props.to ?
        'Link with target: ' + props.target // Error not on ButtonProps
    :
        'Button with disabled: ' + props.disabled; // Error: not on LinkProps

Action({
  to: 'dssd',
  target: '_blank'
});

Saya tidak mengerti sama sekali. Bukankah if ((<A>AorB).a) sama dengan menggunakan if (A.a) karena Anda memaksanya kembali mengetik A ?

Jika Anda menentukan a: undefined pada tipe B, Anda harus menyetelnya ke undefined saat Anda membuat / meneruskan variabel.
Untuk menyiasatinya, Anda dapat mendeklarasikan a sebagai a?: undefined , dan skrip akan senang jika Anda menghilangkannya.

mungkin lebih baik a?: never , sekarang Anda tidak dapat menetapkan undefined karena kesalahan

Bagaimana jika Anda tidak memberikan nama kepada setiap anggota serikat? (tidak dapat membuat pernyataan tipe seperti di atas tanpa nama untuk tipe yang ditegaskan, bukan?)

type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'

Ada solusi?

saya menemukan solusi di buku:

interface A { x:  number;} 
interface B { y:  string;}
function doStuff ( q: A | B ) {
  if ( 'x'  in q) {
    //  if type A...
  }
  else {
    // if type B...
  }
}

Kutipan Dari: Basarat Ali Syed. “TypeScript Deep Dive.” Apple Books.

properti pada objek dan dapat digunakan sebagai pelindung tipe, dan TypeScript dapat mengetahui tipe yang Anda gunakan.

type ColorItemType = {
    colorId: number,
    colorName: string,
}

type NumItemType = {
    numId: number,
    numName: string
}

type ResType = {
    itemId: number,
    // 0 color 1 num
    type: number,
    itemInfo: {
        colorList: Array<ColorItemType>
        numList: Array<NumItemType>
    }
}

const request = () => {
    return [{
        itemId: 1,
        type: 0,
        itemInfo: {
            colorList: [{
                colorId: 1,
                colorName: 'blue'
            }],
            numList: []
        }
    }];
};

const dataSource: Array<ResType> = request();

const formatData = dataSource.map(dataItem => {
    const list: Array<ColorItemType | NumItemType> = dataItem.type === 1 ? dataItem.itemInfo.numList : dataItem.itemInfo.colorList;
    return list.map(listItem => {
        return {
            // An error will be reported here
            value: listItem.numId || listItem.colorId,
            label: listItem.numName || listItem.colorName
        };
    });
});

Masalahnya di sini adalah karena B tidak mendeklarasikan properti a , mungkin pada saat run-time memiliki properti a dari jenis yang mungkin (karena Anda dapat menetapkan objek dengan set properti apa pun menjadi B selama ia memiliki properti tipe string b ). Anda dapat membuatnya bekerja secara eksplisit dengan mendeklarasikan properti a: undefined di B (dengan demikian memastikan bahwa B tidak akan memiliki properti a acak):

type A = { a: string; } 
type B = { b: string; a: undefined }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // Ok
}

Tidak bekerja untuk saya 07.10.2020

Dan menurut saya perilaku TS ini tidak baik karena tidak banyak membantu pengembang ...

Apakah halaman ini membantu?
5 / 5 - 1 peringkat