我有一个类型
export type LocationQuery = {
showWarnings: boolean;
showErrors: boolean;
startDate: string;
endDate: string;
quickDate: number;
}
现在,我想从location.query
模块转换history
以转换为此类型。
这种不方便的方法是手动:
let query: LocationQuery;
query.showWarnings = location.query['showWarnings'];
query.showErrors = location.query['showErrors'];
...
但是有更方便的单线方式吗?请注意location.query
可能包含其他我不关心的字段(如果有location.query['someOtherField']
,则不应进入query
答案 0 :(得分:0)
有太多方法可以做到这一点 这可能是其中之一
import * as assert from "assert";
/**
* will copy all blueprint.keys from source
* or default to blueprint (default) value;
* @returns a copy of blueprint with source values
*/
const copy = <TSource extends {}, TTarget extends {}>
(source: TSource, bluePrint: TTarget): TTarget => {
let result: any = {};
// see: Object.getOwnPropertyNames, its shallow
for (let key of Object.getOwnPropertyNames(bluePrint)) {
result[key] = source.hasOwnProperty(key)
? source[key]
// default to blueprint prop, will be undefined
// but they key will exists
: bluePrint[key];
}
return result;
}
export type LocationQuery = {
showWarnings: boolean;
showErrors: boolean;
startDate: string;
endDate: string;
quickDate: number;
}
interface History {
showWarnings: boolean;
showErrors: boolean;
startDate: string;
endDate: string;
quickDate: number;
somethingElse: any;
}
/**
* Default Value, blueprint, skeleton, shape,etc
*/
const empty: LocationQuery = {
showWarnings: undefined,
showErrors: undefined,
startDate: undefined,
endDate: undefined,
quickDate: undefined,
};
/**
* test's source subject
*/
const history: History = {
showWarnings: false,
showErrors: false,
startDate: '2016-12-01',
endDate: '2016-12-31',
quickDate: 1,
somethingElse: false
}
/**
* LocationQuery it's 'Partial'History
*/
const expected: LocationQuery = {
showWarnings: false,
showErrors: false,
startDate: '2016-12-01',
endDate: '2016-12-31',
quickDate: 1,
}
describe("copy", () => {
it("shallow copy, all desired members", () => {
let result = copy(history, empty);
assert.deepEqual(expected, result);
// All Key Present?
// somethingElse shoudl be missing...
assert.equal(
"showWarnings, showErrors, startDate, endDate, quickDate",
Object.keys(result).reduce( (a,b)=> a+ ", "+b));
});
it("shallow copy, all desired members and defaults to missing props", () => {
// doesn't provide all memebers
const historyLike = {
showWarnings: true,
showErrors: true,
}
let result = copy(historyLike, empty);
const expected_result_with_defaults = {
showWarnings: true,
showErrors: true,
startDate: undefined,
endDate: undefined,
quickDate: undefined,
};
// Values Ok?
assert.deepEqual(expected_result_with_defaults, result);
// All Key Present?
assert.equal(
"showWarnings, showErrors, startDate, endDate, quickDate",
Object.keys(result).reduce( (a,b)=> a+ ", "+b)
)
});
})
Typescript 2.1 +
的另一个/**
* Requires Typescript 2.1 up
* copy specified key from derived type
* where TSource is superset of TResult
*/
const copy = <TSource extends TResult, TResult extends {}>(source: {}, ...keys: (keyof TResult)[]): TResult => {
let result: any = {};
for(let key of keys){
result[key] = source.hasOwnProperty(key) ? (<any>source)[key] : null;
}
return result
}
describe("copy", () => {
it("copy specified members ", () => {
let result = copy<History, LocationQuery>(
/*from*/ history,
"showWarnings" ,
"showErrors",
"startDate",
"endDate",
"quickDate");
assert.deepEqual(expected, result);
assert.equal(
"showWarnings, showErrors, startDate, endDate, quickDate",
Object.keys(result).reduce( (a,b)=> a+ ", "+b)
)
});
})
答案 1 :(得分:0)
使用字段名称列表:
function toLocationQuery(source) {
const fields = ['showWarnings', 'showErrors', 'startDate', 'endDate', 'quickDate']
let res = {}
for (let k of fields) {
if (source[k] === undefined)
throw new Error(`Missing field "${k}"`)
res[k] = source[k]
}
return res as LocationQuery
}
let query = toLocationQuery(location.query)
或相同的代码但不重新声明每个调用的字段列表:
const toLocationQuery = (function () {
const fields = ['showWarnings', 'showErrors', 'startDate', 'endDate', 'quickDate']
return function (source) {
let res = {}
for (let k of fields) {
if (source[k] === undefined)
throw new Error(`Missing field "${k}"`)
res[k] = source[k]
}
return res as LocationQuery
}
})()
let query = toLocationQuery(location.query)