Rumah  >  Artikel  >  hujung hadapan web  >  Pengecualian Masa Kompilasi Kaya dalam TypeScript Menggunakan Jenis Tidak Boleh Dibina

Pengecualian Masa Kompilasi Kaya dalam TypeScript Menggunakan Jenis Tidak Boleh Dibina

Susan Sarandon
Susan Sarandonasal
2024-10-29 18:40:02971semak imbas

Rich Compile-Time Exceptions in TypeScript Using Unconstructable Types

Sistem jenis TypeScript berkuasa, tetapi mesej ralatnya kadangkala boleh menjadi samar dan sukar difahami. Dalam artikel ini, kami akan meneroka corak yang menggunakan jenis yang tidak boleh dibina untuk mencipta pengecualian masa kompilasi yang jelas dan deskriptif. Pendekatan ini membantu mengelakkan ralat masa jalan dengan menjadikan keadaan tidak sah tidak dapat diwakili dengan mesej ralat yang berguna.

Corak: Jenis Tidak Boleh dibina dengan Mesej Tersuai

Pertama, mari kita pecahkan corak teras:

// Create a unique symbol for our type exception
declare const TypeException: unique symbol;

// Basic type definitions
type Struct = Record<string, any>;
type Funct<T, R> = (arg: T) => R;
type Types<T> = keyof T & string;
type Sanitize<T> = T extends string ? T : never;

// The core pattern for type-level exceptions
export type Unbox<T extends Struct> = {
    [Type in Types<T>]: T[Type] extends Funct<any, infer Ret>
        ? (arg: Ret) => any
        : T[Type] extends Struct
        ? {
              [TypeException]: `Variant <${Sanitize<Type>}> is of type <Union>. Migrate logic to <None> variant to capture <${Sanitize<Type>}> types.`;
          }
        : (value: T[Type]) => any;
};

Bagaimana Ia Berfungsi

  1. TypeException ialah simbol unik yang bertindak sebagai kunci khas untuk mesej ralat kami
  2. Apabila kami menemui keadaan jenis tidak sah, kami mengembalikan jenis objek dengan sifat TypeException
  3. Jenis ini tidak boleh dibina pada masa jalan, memaksa TypeScript untuk menunjukkan mesej ralat tersuai kami
  4. Mesej ralat boleh memasukkan maklumat jenis menggunakan literal templat

Contoh 1: Pengendalian Varian dengan Ralat Tersuai

Berikut ialah contoh yang menunjukkan cara menggunakan corak ini dengan jenis varian:

type DataVariant = 
    | { type: 'text'; content: string }
    | { type: 'number'; value: number }
    | { type: 'complex'; nested: { data: string } };

type VariantHandler = Unbox<{
    text: (content: string) => void;
    number: (value: number) => void;
    complex: { // This will trigger our custom error
        [TypeException]: `Variant <complex> is of type <Union>. Migrate logic to <None> variant to capture <complex> types.`
    };
}>;

// This will show our custom error at compile time
const invalidHandler: VariantHandler = {
    text: (content) => console.log(content),
    number: (value) => console.log(value),
    complex: (nested) => console.log(nested) // Error: Type has unconstructable signature
};

Contoh 2: Pengesahan Jenis Rekursif

Berikut ialah contoh yang lebih kompleks yang menunjukkan cara menggunakan corak dengan jenis rekursif:

type TreeNode<T> = {
    value: T;
    children?: TreeNode<T>[];
};

type TreeHandler<T> = Unbox<{
    leaf: (value: T) => void;
    node: TreeNode<T> extends Struct
        ? {
              [TypeException]: `Cannot directly handle node type. Use leaf handler for individual values.`;
          }
        : never;
}>;

// Usage example - will show custom error
const invalidTreeHandler: TreeHandler<string> = {
    leaf: (value) => console.log(value),
    node: (node) => console.log(node) // Error: Cannot directly handle node type
};

Contoh 3: Jenis Pengesahan Negeri

Begini cara kita boleh menggunakan corak untuk menguatkuasakan peralihan keadaan jenis yang sah:

type LoadingState<T> = {
    idle: null;
    loading: null;
    error: Error;
    success: T;
};

type StateHandler<T> = Unbox<{
    idle: () => void;
    loading: () => void;
    error: (error: Error) => void;
    success: (data: T) => void;
    // Prevent direct access to state object
    state: LoadingState<T> extends Struct
        ? {
              [TypeException]: `Cannot access state directly. Use individual handlers for each state.`;
          }
        : never;
}>;

// This will trigger our custom error
const invalidStateHandler: StateHandler<string> = {
    idle: () => {},
    loading: () => {},
    error: (e) => console.error(e),
    success: (data) => console.log(data),
    state: (state) => {} // Error: Cannot access state directly
};

Bila Menggunakan Corak Ini

Corak ini amat berguna apabila:

  1. Anda perlu menghalang gabungan jenis tertentu pada masa penyusunan
  2. Anda ingin memberikan mesej ralat yang jelas dan deskriptif untuk pelanggaran jenis
  3. Anda sedang membina hierarki jenis kompleks di mana operasi tertentu harus dihadkan
  4. Anda perlu membimbing pembangun ke arah corak penggunaan yang betul dengan mesej ralat yang berguna

Butiran Teknikal

Mari kita pecahkan cara corak berfungsi secara dalaman:

// Create a unique symbol for our type exception
declare const TypeException: unique symbol;

// Basic type definitions
type Struct = Record<string, any>;
type Funct<T, R> = (arg: T) => R;
type Types<T> = keyof T & string;
type Sanitize<T> = T extends string ? T : never;

// The core pattern for type-level exceptions
export type Unbox<T extends Struct> = {
    [Type in Types<T>]: T[Type] extends Funct<any, infer Ret>
        ? (arg: Ret) => any
        : T[Type] extends Struct
        ? {
              [TypeException]: `Variant <${Sanitize<Type>}> is of type <Union>. Migrate logic to <None> variant to capture <${Sanitize<Type>}> types.`;
          }
        : (value: T[Type]) => any;
};

Faedah Berbanding Pendekatan Tradisional

  1. Kosongkan Mesej Ralat: Daripada ralat jenis lalai TypeScript, anda mendapat mesej tersuai yang menerangkan dengan tepat apa yang salah
  2. Keselamatan Masa Kompil: Semua ralat ditangkap semasa pembangunan, bukan pada masa jalan
  3. Pendokumentasian Kendiri: Mesej ralat boleh menyertakan arahan tentang cara membetulkan isu itu
  4. Selamat Jenis: Mengekalkan keselamatan jenis penuh sambil memberikan pengalaman pembangun yang lebih baik
  5. Kos Masa Jalan Sifar: Semua semakan berlaku pada masa penyusunan tanpa overhed masa jalan

Kesimpulan

Menggunakan jenis yang tidak boleh dibina dengan mesej ralat tersuai ialah corak yang berkuasa untuk mencipta kekangan jenis pendokumentasian sendiri. Ia memanfaatkan sistem jenis TypeScript untuk memberikan panduan yang jelas pada masa penyusunan, membantu pembangun menangkap dan membetulkan isu sebelum ia menjadi masalah masa jalan.

Corak ini amat berharga apabila membina sistem jenis kompleks di mana kombinasi tertentu seharusnya tidak sah. Dengan menjadikan keadaan tidak sah tidak dapat diwakili dan memberikan mesej ralat yang jelas, kami boleh mencipta kod TypeScript yang lebih boleh diselenggara dan mesra pembangun.

Atas ialah kandungan terperinci Pengecualian Masa Kompilasi Kaya dalam TypeScript Menggunakan Jenis Tidak Boleh Dibina. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn