使用TypeScript,我可以键入getProperty的当前版本吗<;T、 T>;

使用TypeScript,我可以键入getProperty的当前版本吗<;T、 T>;,typescript,generics,currying,Typescript,Generics,Currying,来自 函数getProperty(o:T,名称:K):T[K]{ return o[name];//o[name]的类型为T[K] } 咖喱版: function curriedGetProperty<T, K extends keyof T>(name: K): (o: T) => T[K] { return (o: T) => o[name]; // o[name] is of type T[K] } const record = { id: 4, lab

来自

函数getProperty(o:T,名称:K):T[K]{ return o[name];//o[name]的类型为T[K] } 咖喱版:

function curriedGetProperty<T, K extends keyof T>(name: K): (o: T) => T[K] {
    return (o: T) => o[name]; // o[name] is of type T[K]
}

const record = { id: 4, label: 'hello' }

const getId = curriedGetProperty('id') // Argument of type '"id"' is not assignable to parameter of type 'never'.

const id = getId(record)
函数curriedGetProperty(名称:K):(o:T)=>T[K]{
return(o:T)=>o[name];//o[name]的类型为T[K]
}
const record={id:4,标签:'hello'}
const getId=curriedGetProperty('id')//类型为“id”的参数不能分配给类型为“never”的参数。
const id=getId(记录)

如果您将其分为两个步骤,则可以将其详细程度降至最低,同时可以完全确保类型安全:

interface recordType {
   id: number,
   label: string
}

const record = { id: 4, label: 'hello' };

const getPropertyBuilder = function <T>() {
   return <K extends keyof T>(key: K) => (o: T) => o[key];
};

const propertyBuilder = getPropertyBuilder<recordType>();
const getId = propertyBuilder('id'); // getId is (o: recordType) => number
const id = getId(record); // id is number

// or in one go
const label = getPropertyBuilder<recordType>()('label')(record); // label is string

使用TypeScript
3.0.3
我能够做到这一点:

function composeGetter<K extends string>(prop: K) {
    function getter<T extends { [P in K]?: any }>(object: T): T[typeof prop]
    function getter<T extends { [P in K]: any }>(object: T) {
        return object[prop]
    }

    return getter
}
功能组合器(prop:K){
函数getter(对象:T):T[typeof prop]
函数getter(对象:T){
返回对象[prop]
}
回程吸气剂
}

是的,这也行。除了
getId
现在不那么灵活之外。我将无法传递
Partial
函数curriedGetProperty(名称:K){
必须以这种方式键入,并且
const getId=curriedGetProperty('id'))
。否则,
getId
的结果是
number | string
@chautelly它似乎无法避免类型为
string | number
,即使使用
K
它也对我有效。您是否像这样调用
curriedGetProperty
curriedGetProperty(/id'))
好的,是的,你把类型缩小到了“id”,结果也缩小了。这完全绕过了类型系统。你现在可以在任何对象上调用它,不管它是否具有正确的属性。你可能一开始就不使用TypeScript。不完全是@dave cousineau。是的,你可以将任何内容传递给
getId
。但是,结果将被相应地键入。如果您通过
getId({})
,您将得到
any
。但是如果您通过
getId({id:4})
,结果将被键入一个数字。或者如果您通过
getId({id:undefined}作为部分)
您将得到
number | undefined
@chautelly
getId
可以用任何东西调用,但是
getProperty
也可以用任何东西调用。但是如果使用正确,它确实会返回正确的类型。使用@kingdaro的答案,
getId(reocrd)
为我返回一个
数字
类型。但是,这不适用于
部分
。除非通过在
之前添加一个
使
部分
类似:
这允许
getId({})
返回
任何
。但不允许
getId(434343434)
getId>(null)
我认为这和我的差不多,尽管你的不需要第二步,所以这实际上可能更好。你说它允许
getId({})
但对我来说它不允许。你说它不允许
getId(null)
但对我来说确实如此。我不认为在不启用严格的空检查的情况下,您可以避免通过
null
未定义的
。您也不会绑定到特定类型
t
,直到您使用它,这使得属性getter可以在任何更好的对象上进行强类型输入。这就是现在的bes我没有回答。是的,我确实为我的项目启用了
stricknullchecks
// implementation
const get = <K extends string>(key: K) => <V>(obj: Record<K, V>) => obj[key]

// usage
const person = {
  name: "kingdaro",
  age: 21,
}

const fruit = {
  type: "apple",
  color: "red",
}

const nameGetter = get("name")

nameGetter(person) // return type inferred as string
nameGetter(fruit) // fails, fruit has no key "name"

// minor caveat: when passing an object literal, the extra key will raise an error
// you can declare the object separately to sidestep around this
// but this wouldn't come up often anyway
nameGetter({ name: "kingdaro", age: 21 })
interface recordType {
   id: number,
   label: string
}

const record = { id: 4, label: 'hello' };

const getPropertyBuilder = function <T>() {
   return <K extends keyof T>(key: K) => (o: T) => o[key];
};

const propertyBuilder = getPropertyBuilder<recordType>();
const getId = propertyBuilder('id'); // getId is (o: recordType) => number
const id = getId(record); // id is number

// or in one go
const label = getPropertyBuilder<recordType>()('label')(record); // label is string
const propertyBuilder = getPropertyBuilder<Partial<typeof record>>();
const getId = propertyBuilder('id');
const id = getId(record); // id is number
const id2 = getId({ id: 3 }); // also number
type WithProp<T extends any, K extends string> = { [P in K]: T[P] }

function curriedGetProperty <P extends string>(prop: P) {
  return <T, O extends WithProp<T, typeof prop>>(o: O) => {
    return o[prop]
  }
}
const getId = curriedGetProperty('id')
getId({id: 'foo'}) // returns string
getId({label: 'hello'}) // fails
function composeGetter<K extends string>(prop: K) {
    function getter<T extends { [P in K]?: any }>(object: T): T[typeof prop]
    function getter<T extends { [P in K]: any }>(object: T) {
        return object[prop]
    }

    return getter
}