簡體   English   中英

根據Typescript中的輸入轉換器函數更改函數返回類型

[英]Change function return type based on input tranformer function in Typescript

我想要做的是創建一個簡單的函數,它可以選擇接受一個transformer方法作為輸入並返回:

  • 原始結果(如果沒有提供transformer
  • 或基於transformer返回類型的轉換結果。

展示我的意思的一個小例子如下:

// our basic example interface
interface Person {
  name: string;
  age: number
};

// the transformer fn type
type TransformerFn = <T>(person: Person) => T;

// method options contaning the optional transformer method param
interface mapperOpts {
  paramA?: number
  transformer?: TransformerFn
}

// Conditional type for returning the result based on providing transformer in options or not
type OriginalOrTransformedPerson<T extends Partial<mapperOpts>> = T extends { transformer: TransformerFn } ? 
  ReturnType<T['transformer']> :
  Person;

// test class interface
interface PeopleGetter {
  getPeople<T extends Partial<mapperOpts>>(people: Person[], opts: T): OriginalOrTransformedPerson<T>
}

class Test implements PeopleGetter {
  getPeople(people: Person[], opts: Partial<mapperOpts>) {
    if (opts.transformer) {
      return people.map(opts.transformer);
    } else {
      return people;
    }
  }
}

const people: Person[] = [{ name: 'john', age: 20 }];

const test = new Test();
const original = test.getPeople(people); // here we should have `Person[]`
const transformedResult = test.getPeople(people, { transformer: (person: Person) => person.name }); // here I would like to have the return type of 'string[]' based on transformer method

打字稿操場在這里

我試圖遵循Array<T>接口的普通map實現,它正確推斷了map提供的回調方法的返回類型,但我無法讓它工作。 我在getPeople實現和使用中遇到錯誤。

有任何想法嗎?

我試圖簡化並創建一個更通用的問題版本並將其發布在這里: Typescript method return type based on optional param property function

在@jcalz 非常慷慨的幫助和解釋下,我還能夠創建一個適用於我的原始帖子的版本。 類型推斷對於 Typescript 來說是一件非常復雜的事情,並不是所有的事情都會像人們期望的那樣自動推斷出來。 重要的結論是:

  • 類型推斷不考慮通用約束
  • 類型推斷不能部分工作。 您要么提供類型化函數使用中的所有類型參數,要么不提供。 您不能提供類型參數之一並讓其他類型參數被推斷出來。

話雖如此,這是適用於我的原始問題的版本:

// our basic example interface
interface Person {
  name: string;
  age: number
};

// the transformer fn type
type TransformerFn<T = any> = (person: Person) => T;

// method options contaning the optional transformer method param
interface mapperOpts<T = any> {
  paramA?: number
  transformer?: TransformerFn<T>
}

// Conditional type for returning the result based on providing transformer in options or not
type OriginalOrTransformedPerson<T> = T extends { transformer: TransformerFn<infer R> } ? 
  R :
  Person;

// test class interface
interface PeopleGetter {
  getPeople<T extends Partial<mapperOpts>>(people: Person[], opts: T): OriginalOrTransformedPerson<T>[]
}

class Test implements PeopleGetter {
  getPeople<T extends Partial<mapperOpts>>(people: Person[], opts?: T): OriginalOrTransformedPerson<T>[] {
    if (opts?.transformer) {
      return people.map(opts.transformer);
    } else {
      return people as OriginalOrTransformedPerson<T>[];
    }
  }
}

const people: Person[] = [{ name: 'john', age: 20 }];

const test = new Test();
const original = test.getPeople(people); // here we should have `Person[]`
const transformedResult = test.getPeople(people, { transformer: (person: Person) => person.name }); // here I would like to have the return type of 'string[]' based on transformer method

打字稿游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM