Typescript 定义方法&x27;使用keyof时的返回类型

Typescript 定义方法&x27;使用keyof时的返回类型,typescript,maybe,Typescript,Maybe,在访问对象的属性之前,想要创建一个包含一些对象的类,并执行空/未定义的检查。 当然,应该键入结果(可能或) 以下是一个例子: class Maybe < T > { constructor(public value: T) {} static of < P > (obj: P): Maybe < P > { return new Maybe(obj); } map < TResult > (fn: (arg: T) =&g

在访问对象的属性之前,想要创建一个包含一些对象的类,并执行空/未定义的检查。 当然,应该键入结果(可能

以下是一个例子:

class Maybe < T > {
  constructor(public value: T) {}
  static of < P > (obj: P): Maybe < P > {
    return new Maybe(obj);
  }

  map < TResult > (fn: (arg: T) => TResult): Maybe < TResult > {
    return this.isNothing ? nothing : new Maybe(fn(this.value));
  }

  public get < P extends keyof T > (name: P): Maybe < T[P] > {
    return this.isNothing ? nothing : Maybe.of(this.value[name]);
  }
  get isNothing(): boolean {
    return this.value == null;
  }
}
let nothing = new Maybe(null);
但在定义“apply”函数时遇到问题,该函数将接受对象属性的名称,实际上是一个函数,执行该函数并返回

  // T[fName]: (...args)=> TResult
  public apply < P extends keyof T > (fnName: P, ...args: any[]) /*: Maybe<Tresult> */ {
    if (!this.isNothing) {
      let res = null;
      let fn = this.value[fnName];

      if (isF(fn)) {
        return Maybe.of(fn(...args));
      }

    }
    return nothing;
  }
//T[fName]:(…args)=>TResult
public apply

(fnName:P,…args:any[])/*:Maybe*/{ 如果(!this.isNothing){ 设res=null; 设fn=this.value[fnName]; 如果(isF(fn)){ (fn(…args))的返回值; } } 一无所获; }

找不到定义“应用”调用结果的解决方案

让fResult=Maybe.of(t).apply('f','foo');
//弗雷索也许是


谢谢

首先,让我把
课放到一边,一步一步地介绍一些基本操作

可以使用泛型函数检查对象是否为null,然后返回该对象的某些属性。可以从属性的类型推断函数的返回类型:

function maybeGet<T, N extends keyof T>(t: T | undefined, n: N) {
  return t ? t[n] : undefined;
}
你可以这样使用它

const a = maybeGet(t, 'a');
实际上,
a
的类型被推断为
{id:number;name:string;}

然后,您可以定义泛型类型别名来描述返回类型为
R
的函数:

type FR<R> = (...args: any[]) => R;
问题是如何将这两种操作组合在一个通用操作中

使用映射类型,您可以尝试为具有返回
R
作为属性的函数的对象定义类型别名

type FM<N extends string, R> = {[n in N]: FR<R>};
但是,它不适用于您的测试,因为TypeScript出于某种原因将使用
keyof T
作为
N
,并坚持要求
test
中的所有属性都必须可调用:

const tm = maybeApplyMemberFunction(t, 'f');

// Argument of type 'Test' is not assignable to parameter of type 
// 'FM<"a" | "f", Test>'.
  // Types of property 'a' are incompatible.
    // Type '{ id: number; name: string; }' is not assignable to type 'FR<Test>'.
      //  Type '{ id: number; name: string; }' provides no match for the signature
      // '(...args: any[]): Test'.

不幸的是,typescript无法指定
N
应该是
N
参数的确切文本类型。

我不清楚您的问题是什么。在您的代码中,您只是忘记声明类型参数
Tresult
。没关系,我误读了,我明白了问题所在。我想这个问题可以浓缩一点,你想要什么还不清楚。似乎您只是在问如何在使用
keyof
时获取方法的返回类型。如果没有检测并确保“f”确实是函数名的方法(以某种方式表示
P extends-keyof-T,TR,T[P]extends(…args:any[])=>TR我不确定这是否可行。
type FR<R> = (...args: any[]) => R;
function maybeApplyFunction<R>(f: FR<R> | undefined, ...args: any[]) {
  return f ? f(...args) : undefined; 
}

const r = maybeApplyFunction(t.f, 'foo'); // r has type 'Test'
const tf = maybeApplyFunction(maybeGet(t, 'f'), 'foo'); 
// tf has type `Test`
type FM<N extends string, R> = {[n in N]: FR<R>};
function maybeApplyMemberFunction<N extends string, R>(o: FM<N, R>, n: N, ...args: any[]) {
  return o ? o[n](...args) : undefined;
}
class T1 { f() { return new T1() } };

const b = maybeApplyMemberFunction(new T1(), 'f');
// b has type T1
const tm = maybeApplyMemberFunction(t, 'f');

// Argument of type 'Test' is not assignable to parameter of type 
// 'FM<"a" | "f", Test>'.
  // Types of property 'a' are incompatible.
    // Type '{ id: number; name: string; }' is not assignable to type 'FR<Test>'.
      //  Type '{ id: number; name: string; }' provides no match for the signature
      // '(...args: any[]): Test'.
function maybeApplyMemberFunctionF<N extends 'f', R>(o: FM<N, R>, n: N, ...args: any[]) {
  return o ? o[n](args) : undefined;
}
const t1 = maybeApplyMemberFunctionF(t, 'f');