Saya memiliki kelas Car, yang mendefinisikan properti untuk model mobil.

Hanya ada 3 model yang mungkin: 'ModelT', 'ModelQ' dan 'ModelX'. Jadi saya telah memutuskan untuk mendefinisikan tipe Model seperti:

type Model = 'ModelT' | 'ModelQ' | 'ModelX';

Dan metode konstruktor Mobil sebagai

class Car {
  constructor(model: Model) {
    this.model = model;
  }
}

Ada juga layanan jarak jauh yang mengembalikan jenis mobil yang harus saya beli. Jika saya menggunakan layanan seperti itu, kode saya terlihat seperti

const model = getModelFromRemoteService();
const car = new Car(model);

Manakah cara terbaik untuk menerapkan logika untuk memeriksa saat runtime bahwa model yang dikembalikan oleh layanan jarak jauh sebenarnya adalah salah satu dari yang ditentukan dalam definisi type Model?

0
Picci 17 Maret 2019, 15:59

1 menjawab

Jawaban Terbaik

Tidak mungkin memulai dengan tipe/antarmuka dan mendapatkan perilaku runtime darinya. Sistem tipe di TypeScript hanya ada pada saat Anda menulis program. Ini sepenuhnya terhapus dari JavaScript yang dipancarkan yang dieksekusi pada saat runtime.

Untungnya, Anda dapat melakukan kebalikannya: mulai dengan objek yang ada saat runtime dan dapatkan kompiler TypeScript untuk menyimpulkan tipe analog untuknya. Dalam kasus Anda, saya sarankan memulai dengan larik nilai yang ingin Anda periksa, dan lanjutkan seperti yang dijelaskan di sini:

// helper function needed before TS3.4 to get a tuple of string literals
// instead of just string[]
const stringTuple = <T extends string[]>(...args: T) => args;

const models = stringTuple('ModelT', 'ModelQ', 'ModelX');
// inferred type of models is ['ModelT', 'ModelQ', 'ModelX'];

// in TS3.4+, const models = ['ModelT', 'ModelQ', 'ModelX'] as const;

type Model = typeof models[number];
// inferred type of Model is 'ModelT' | 'ModelQ' | 'ModelX'

Sekarang Anda memiliki Model mengetik kembali, dan Anda juga memiliki nilai array models yang dapat Anda gunakan untuk membuat ketik pelindung untuknya:

function isModel(x: any): x is Model {
  return models.indexOf(x) >= 0;
  // or return models.includes(x) for ES2016+
}

Dan sekarang Anda dapat menggunakannya seperti ini:

class Car {
  model: Model;
  constructor(model: Model) {
    this.model = model;
  }
}
// assume this returns a string
declare function getModelFromRemoteService(): string;

// wrap getModelFromRemoteService so that it returns a Model 
// or throws a runtime error
function ensureModelFromRemoteService(): Model {
  const model = getModelFromRemoteService();
  if (isModel(model)) return model;
  throw new Error("THAT REMOTE SERVICE LIED TO ME");
}


const model = ensureModelFromRemoteService();
const car = new Car(model); // works now

Oke, semoga membantu. Semoga berhasil!

1
jcalz 17 Maret 2019, 17:20