ค้นหาเว็บไซต์

เปลี่ยนชื่อคีย์ของประเภทอ็อบเจ็กต์ TypeScript


ฉันมีอันนี้:

type Two = {
  one: number,
  two: string,
  three: boolean
}

ฉันต้องการให้มันสร้างประเภทที่ดูเหมือนแบบนี้:

type RenamedTwo = {
  one: number,
  two: string,
  four: boolean // difference
}

พยายามสร้างมันด้วยวิธีนี้:

type Rename<T, K extends keyof T, N> = Pick<T, Exclude<keyof T, K>> & { [N]: T[K] }

ในการพยายามใช้วิธีนี้:

type Renamed = Rename<Two, 'three', 'four'>

แต่ TSlint ทำเครื่องหมาย [N] เป็นข้อผิดพลาดและให้ข้อความข้อผิดพลาดนี้:

[ts] ชื่อสมบัติที่คำนวณได้ในไทป์ลิเทอรัลต้องอ้างอิงถึงนิพจน์ที่มีไทป์เป็นไทป์ลิเทอรัลหรือไทป์ 'unique symbol' [ts] 'N' อ้างถึงไทป์เท่านั้น แต่ถูกใช้งานเป็นค่าที่นี่

คำตอบ #1

คุณต้องใช้ชนิดที่แมปสำหรับคุณสมบัติที่ถูกเปลี่ยนชื่อด้วย:

type Two = {
    one: number,
    two: string,
    three: boolean
}


type Rename<T, K extends keyof T, N extends string> = Pick<T, Exclude<keyof T, K>> & { [P in N]: T[K] }

type Renamed = Rename<Two, 'three', 'four'>

โปรดทราบว่าสิ่งนี้จะไม่ทำงานตามที่คาดไว้หากคุณให้คุณสมบัติเพิ่มเติม:

type Renamed = Rename<Two, 'two'  |'three' , 'four' | 'five'> // will be Pick<Two, "one"> & {
//    four: string | boolean;
//    five: string | boolean;
// }

คำตอบ #2

ในเวอร์ชัน TypeScript ปัจจุบัน 4.6.2 มีแกรมมาที่สามารถแมปใหม่ได้เพื่อใช้งาน ซึ่งสามารถนำไปใช้งานได้ง่ายขึ้นมาก

PlayGround

type RenameByT<T, U> = {
  [K in keyof U as K extends keyof T
    ? T[K] extends string
      ? T[K]
      : never
    : K]: K extends keyof U ? U[K] : never;
};

type Two = { one: number; two: string; three: boolean };

// returnType = { one: number; two: string, four: boolean };
type renameOne = RenameByT<{three: 'four', five: 'nouse'}, Two>;

// returnType = { x: number, y: string, z: boolean; }
type renameAll = RenameByT<{one: 'x', two: 'y', three: 'z'}, Two>;

ชนิด RenameByT สามารถแยกออกเป็นหลายส่วน คำอธิบายนี้สำหรับตัวอย่าง renameOne

  1. `K in keyof U` หมายถึงทุกคีย์ใน `U` ตัวอย่างเช่น `one | two | three`
  2. ข้อ as สามารถใช้ได้ตั้งแต่ ts4.1 แต่ฉันไม่สามารถใช้ใน 4.4.4 ได้ แต่สามารถใช้ใน 4.6.2 นี่ใช้เพื่อเปลี่ยนชื่อ Key K ตามประเภทเงื่อนไข
  3. K extends keyof T. keyof T หมายถึง three | five.
  4. T[K] extends string หมายความว่า T[K] เป็น string. T['three'] เป็น string ดังนั้นจะส่งกลับ four, T['five'] ส่งกลับ nouse;
  5. ชนิดผลลัพธ์ K extends keyof U, ดังนั้น T['three'] จึงเป็นไปตามเงื่อนไข ดังนั้นผลลัพธ์จะเป็น { four: U['three'] } หมายถึง { four: boolean}
  6. คีย์อื่นๆ คืนค่าเป็นค่าเริ่มต้น

แหล่งอ้างอิง:

https://github.com/microsoft/TypeScript/issues/40833 https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

บทความที่เกี่ยวข้อง