是否可以构造一个TypeScript类型,它只会选择那些类型为X的属性?
interface IA {
a: string;
b: number;
}
interface IB extends IA {
c: number | string;
}
type IAStrings = PickByType<IA, string>;
// IAStrings = { a: string; }
type IBStrings = PickByType<IB, string>;
// IBStrings = { a: string; }
type IBStringsAndNumbers = PickByType<IB, string | number>;
// IBStringsAndNumbers = { a: string; b: number; c: number | string; }
答案 0 :(得分:6)
是的,这是可能的。我也遇到了这个问题,也在寻找答案,但最终我想通了。
TL; DR
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Whenever there's a reusable cell available, dequeue will return it
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") ??
UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier")
更长的解释版本
/**
* Returns an interface stripped of all keys that don't resolve to U, defaulting
* to a non-strict comparison of T[key] extends U. Setting B to true performs
* a strict type comparison of T[key] extends U & U extends T[key]
*/
type KeysOfType<T, U, B = false> = {
[P in keyof T]: B extends true
? T[P] extends U
? (U extends T[P]
? P
: never)
: never
: T[P] extends U
? P
: never;
}[keyof T];
type PickByType<T, U, B = false> = Pick<T, KeysOfType<T, U, B>>;
因此,class c1 {
a: number;
b: string;
c: Date;
d?: Date;
};
type t1 = keyof c1; // 'a' | 'b' | 'c' | 'd'
type t2 = Pick<c1, t1>; // { a: number; b: string; c: Date; d?: Date; }
type KeysOfType0<T, U> = {
[P in keyof T]: T[P] extends U ? P : never;
};
type t3 = KeysOfType0<c1, Date>; // { a: never; b: never; c: "c"; d?: "d"; }
// Based on https://github.com/microsoft/TypeScript/issues/16350#issuecomment-397374468
type KeysOfType<T, U> = {
[P in keyof T]: T[P] extends U ? P : never;
}[keyof T];
type t4 = KeysOfType<c1, Date>; // "c" | "d"
type t5 = Pick<c1, t4>; // { c: Date; d?: Date; }
type PickByType<T, U> = Pick<T, KeysOfType<T, U>>;
type t6 = PickByType<c1, Date>; // { c: Date; d?: Date; }
可以准确给出您在注释中得到的结果。
如果需要严格类型的实用程序,则需要验证扩展是双向的。下面是一个示例示例,其中原始的KeysOfType实用程序可能返回意外结果,并且提供了两种解决方案。
在typescript playground上尝试一下。
PickByType
答案 1 :(得分:0)
将来可以使用enhancements to Mapped Types来完成此操作。
在那之前,你可以分解你的界面,虽然我只推荐它,如果它有意义:
interface IA {
a: string;
}
interface IA2 extends IA {
b: number;
}
interface IB extends IA2 {
c: number | string;
}
这会为您提供您尝试计算的IA
类型。
如果这没有意义,那就是手动创建IAStrings
界面的情况,该界面只包含您希望它拥有的属性。