เปลี่ยนชื่อคีย์ของประเภทอ็อบเจ็กต์ 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
- `
K in keyof U` หมายถึงทุกคีย์ใน `U` ตัวอย่างเช่น `one | two | three` - ข้อ
asสามารถใช้ได้ตั้งแต่ ts4.1 แต่ฉันไม่สามารถใช้ใน 4.4.4 ได้ แต่สามารถใช้ใน 4.6.2 นี่ใช้เพื่อเปลี่ยนชื่อ KeyKตามประเภทเงื่อนไข K extends keyof T. keyof T หมายถึงthree | five.T[K] extends stringหมายความว่าT[K]เป็น string.T['three']เป็น string ดังนั้นจะส่งกลับfour,T['five']ส่งกลับnouse;- ชนิดผลลัพธ์
K extends keyof U, ดังนั้นT['three']จึงเป็นไปตามเงื่อนไข ดังนั้นผลลัพธ์จะเป็น{ four: U['three'] }หมายถึง{ four: boolean} - คีย์อื่นๆ คืนค่าเป็นค่าเริ่มต้น
แหล่งอ้างอิง:
https://github.com/microsoft/TypeScript/issues/40833 https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
