你可以排序做你想要的,但不是自動的。大阻滯劑是,目前還no type operator,讓您在類型級別追加字符串文字,所以你甚至不能形容你在做轉型:這意味着你需要真正的硬編碼
// without Append<A extends string, B extends string>, you can't type this:
function appendChange<T extends string>(originalKey: T): Append<T,'Change'> {
return originalKey+'Change';
}
你正在尋找的具體映射,從字符串文字到字符串文字。事實上,我能得到這個工作的唯一方法是指定反向映射:
type SomeMoreDataMapping = {
prop1Change: 'prop1';
prop2Change: 'prop2';
}
武裝與反向映射,您可以定義這些:
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = {[P in Diff<keyof T, K>]: T[P]};
type Dict<T> = { [k: string]: T };
type MapKeys<T extends Dict<any>, M extends Dict<string>> = {
[K in keyof M]: T[M[K]];
} & Omit<T, M[keyof M]>;
(其中一些是。需要打字稿V2.4及以上如果您使用的打字稿的早期版本,請參閱this issue的方式來實現Diff
和Omit
)
簡要runthrough:
Diff<T,U>
對字符串文字類型的聯合起作用,將U
中的那些從T
中的那些中刪除。
Omit<T,K>
從對象類型T
中刪除K
中的所有屬性。
Dict<T>
只是一個字符串鍵的對象,其屬性都是T
。
- 最後是
MapKeys<T,M>
是你想要的東西:它需要對象T
並根據M
中的反向映射來轉換密鑰。如果密鑰T
不存在於M
中,則密鑰不會被轉換。如果M
中的密鑰不存在於T
中,它將出現在帶有any
類型的輸出中。
現在你可以(終於)做到這一點:
type SomeMoreData= MapKeys<SomeData, SomeMoreDataMapping>;
如果你檢查SomeMoreData
,你看它有權利類型:
var someMoreData: SomeMoreData = {
prop1Change: 'Mystery Science Theater',
prop2Change: 3000
} // type checks
這應該允許您做一些有趣的事情,如:
function makeTheChange<T>(input: T): MapKeys<T, SomeMoreDataMapping> {
var ret = {} as MapKeys<T, SomeMoreDataMapping>;
for (var k in input) {
// lots of any needed here; hard to convince the type system you're doing the right thing
var nk: keyof typeof ret = <any>((k === 'prop1') ? 'prop1Change' : (k === 'prop2') ? 'prop2Change' : k);
ret[nk] = <any>input[k];
}
return ret;
}
var changed = makeTheChange({ prop1: 'Gypsy', prop2: 'Tom', prop3: 'Crow' });
console.log(changed.prop1Change.charAt(0)); //ok
console.log(changed.prop2Change.charAt(0)); //ok
console.log(changed.prop3.charAt(0)); //ok
希望有幫助。祝你好運!
循環播放SomeData []並填充SomeMoreData []是一個選項。 – adiga
這不會給我類型驗證問題嗎?我試圖避免在那裏有一個「任何」對象。 – Tony