TypeScript:条件类型不使用可选参数

hwazgwia  于 2023-01-27  发布在  TypeScript
关注(0)|答案(2)|浏览(229)

我有一个数据源,我们叫它getData(),它返回对象,有时它返回已知类型的对象(例如PersonAnimal),但有时返回的对象具有未知的形状。
(Link到TypeScriptPlayground)

type Person = { name: string; age: number };
type Animal = { species: string };

/** 
 * This interface stores all known object types returned by `getData()`.
 * I'm storing it as an interface instead of `Person | Animal` because I
 * need to store the "code" of a known type (e.g. `"person"` for `Person` type).
 */
interface DataCategory {
  person: Person;
  animal: Animal;
}

/** Our data source */
const getData: Person | Animal | any = () => {
  return {};  // Mocked value
};

现在我想写一个helper函数useData()来缩小getData()的返回值。它接受keyof DataCategory类型的可选参数并返回相应的类型。我想让这个函数返回any如果我们不传递参数

const person = useData("person");  // const person: Person
const animal = useData("animal");  // const animal: Animal
const notKnown = useData();   // const notKnown: any

我尝试了以下实现:

function useData<T extends keyof DataCategory>(category?: T) {
  const data: any = getData();
  return data as T extends undefined ? any : DataCategory[T];
}

const animal = useData("animal");
//    ^ const animal: Animal

const notKnown = useData();
//    ^ const notKnown: Person | Animal
// However, I want the above to be `const notKnown: any`

这不起作用,因为useData()返回Person | Animal而不是any。如何解决此问题?

p3rjfoxz

p3rjfoxz1#

默认情况下,TS将使用约束作为它无法推断的类型参数的类型(在这种情况下,没有位置可供推断T),您可以通过使用any作为默认值来更改此设置:

function useData<T extends keyof DataCategory = any>(category?: T) {
  const data: any = getData();
  return data as T extends undefined ? any : DataCategory[T];
}

Playground链接
正如Michael Rose在他的回答中指出的,您也可以使用重载,它们可能更容易为未来的读者所理解。

krcsximq

krcsximq2#

尝试使用泛型的另一种方法是重载useData函数并指定类别:

function useData(category: "animal"): Animal;
function useData(category: "person"): Person;
function useData(): any;
function useData(category?: string): any {
  return getData();
}

const animal = useData("animal");
//    ^ const animal: Animal

const notKnown = useData();
//    ^ const notKnown: any

相关问题