我正在尝试从模型级别之一返回值。第一层完美地工作,因为返回值的类型为T [K],这意味着['Login','Password','Address']返回我想要的内容。但是当我改变
getProperty(auth, x => x.Address);
至
getProperty(auth, x => x.Address.Address2);
。
我知道'Address2'属性不是直接在T类型下。
我不知道哪种类型的更改'T [K]'也可以使用。 Address2属性。
你能帮我吗?
编辑:getProperty(auth, x => x.Address.Address2.State);
的怪异之处
export interface Auth {
Login: string;
Password: string;
Address: {
Address2: {
State: string;
}
}
}
let auth: Auth = {
Login: 'login',
Password: 'password',
Address: {
Address2:{
State: 'some state'
}
}
};
function getProperty<T, K extends keyof T>(obj: T, fn: (m: T) => T[K]) {
console.log(fn(obj));
}
getProperty(auth, x => x.Address.Address2);
答案 0 :(得分:1)
function getProperty<T, B>(obj: T, fn: (m: T) => B): B {
return fn(obj);
}
const testType = getProperty(auth, x => x.Address.Address2); // string.
希望这会有所帮助,据我所知,无法对类型进行加深的事实是您的函数返回由T的索引产生的类型,因为无法表示此“加深”。 I.E您可以表达T [K],但只能达到1的深度。可以完全表达深度键访问的另一种语法如下:
interface IGetProperty<Original, Access> {
value: Access,
pick: <K extends keyof Access>(key: K) => IGetProperty<Original, Access[K]>
}
const getProperty = <Original, Access = Original>(obj: Original): IGetProperty<Original, Access> => {
return {
value: obj as any,
pick: (key) => getProperty((obj as any)[key as any]) as any
}
}
const testType = getProperty(auth).pick("Address").pick("Address2").pick("State").value // string.
const testType = getProperty(auth).pick("Address").pick("Invalid Key").pick("State").value // Error.
编辑:在打字稿中,即使您可以键入一个函数返回T [K],也不会“强制”该函数返回一些从“ T”索引的值,因为如果T [K]是字符串,那么您可以返回任何字符串,例如不是来自“ T”的“ hello”,它仍然会进行类型检查,这是因为如果您使用的是T [K]的类型,那么Typescript键入的东西在结构上并不是名义上的,则这种行为是可能的在全球范围内
答案 1 :(得分:0)
我不是100%确信我理解用例,但是您可以使用运行时不存在的幻像类型,将回调限制为“返回(可能嵌套的)属性的东西”。像这样:
object
这个想法是,我们假装传入的对象不是 declare class DeepDooDoo {private dooDoo: true};
type DeepVooDoo<T> = DeepDooDoo & (T extends object ? {
[K in keyof T]: DeepVooDoo<T[K]>
} : T)
function getProperty<T, U>(obj: T, fn: (m: DeepVooDoo<T>)=>DeepVooDoo<U> ): void {
console.log(fn(obj as DeepVooDoo<T>));
}
类型,而是T
类型。这是幻影类DeepVooDoo<T>
的实例,并且(由于递归映射类型定义),其所有属性本身都是DeepDooDoo
实例,并且它们的所有属性,等等。回调函数受到限制到接受DeepDooDoo
并为某些DeepVooDoo<T>
返回DeepVooDoo<U>
的事物。这或多或少意味着您必须返回传入对象的属性或子属性(或子子属性等)。如果尝试返回其他内容,则编译器可能会注意到不是U
并抱怨。
让我们尝试一下:
DeepDooDoo
看起来很好。幻像类型有点滥用类型系统,因此很可能会产生奇怪的副作用。如果您决定继续执行此类操作,请小心操作并确保它适合您的用例。
好的,希望能有所帮助。祝你好运!