如何从TSource和给定的属性名称(TSource的键)推断结果类型(TTarget)?
我具有以下功能,可将定义的属性复制到新对象中:
export declare type PropertyNamesOnly<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
CopyProps<TSource, TTarget>(source: TSource, ...props: PropertyNamesOnly<TSource>[]): TTarget {
const result: any = {};
for (const prop of props) {
result[prop] = source[prop];
}
return result;
}
现在我可以这样使用它:
class Props { a: string = "a"; b: string = "b"; c: string = "c"; }
const props = new Props();
const copy = CopyProps<Props, Omit<Props, "b">>(props, "a", "c");
expect(copy.a).to.equal("a");
// copy has omitted property b
expect((copy as any).b).to.be.undefined;
expect(copy.c).to.equal("c");
但是我不想定义TSource和TTarget。我想要这个:
CopyProps<TSource>(source: TSource, ...props: PropertyNamesOnly<TSource>[]): TypeFromProps<props> {
const result: any = {};
for (const prop of props) {
result[prop] = source[prop];
}
return result;
}
// Then copy should contains only property a and c
const copy = CopyProps(props, "a", "c");
如何获取TypeFromProps类型?
解决方案:
static PickProps<
TSource,
Props extends PropertyNamesOnly<TSource>,
TTarget extends Pick<TSource, Props>>
(source: TSource, ...props: Props[]): TTarget {
const result: any = {};
for (const prop of props) {
result[prop] = source[prop];
}
return result;
}
static OmitProps<
TSource,
Props extends PropertyNamesOnly<TSource>,
TTarget extends Omit<TSource, Props>>
(source: TSource, ...props: Props[]): TTarget {
const result: any = {};
const keys = Object.keys(source).filter(k => props.some(p => p !== k)) as (keyof TSource)[];
for (const key of keys) {
result[key] = source[key];
}
}
答案 0 :(得分:1)
为了实现此目标,我们需要将属性类型提升为泛型。考虑:
declare type PropertyNamesOnly<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
function CopyProps<
TSource,
Props extends PropertyNamesOnly<TSource>,
TTarget extends Pick<TSource, Props>>
(source: TSource, ...props: Props[]): TTarget {
const result: any = {};
for (const prop of props) {
result[prop] = source[prop];
}
return result;
}
class Props { a: string = "a"; b: string = "b"; c: string = "c"; }
const props = new Props();
const copy = CopyProps(props, "a", "c"); // copy has a and c
// second check with function
const example2 = { a: 'a', b: () => { }, c: 1 };
const copy2 = CopyProps(example2, "a", "b"); // correct error as b is a function
const example3 = { a: 'a', b: () => { }, c: 1 };
const copy3 = CopyProps(example2, "a", "c"); // is ok has a and c
最重要的部分:
Props extends PropertyNamesOnly<TSource>
-我们说道具是TSource
的键,但没有功能值类型的键TTarget extends Pick<TSource, Props>
-我们说归还将是TSource
的对象,并由Props
挑选道具...props: Props[]
我们声明我们的道具是泛型,以便类型推断起作用