如何扁平化打字稿中的泛型类型声明?

acr*_*ing 1 generics typescript

案件:

函数输入一个嵌套的通用对象,并输出平面对象,如下所示:

interface Deep<T> {
  p1: T;
  p2: T;
}

type Nested<T> = {
  [P in keyof T]: Deep<any>;
}

type Flat<T, ?> = {
  [P in keyof T]: T[P]?;
}

function flat<T extends Nested<T>>(input: T, p: keyof Deep<any>): Flat<T, ?> {
  const put: any = {}
  for (let k in input)
    put[k] = input[k][p]
}

const foo = flat({
  name: { p1: 'name', p2: 'name' },
  { fn: { p1: () => 0, p2: () => 1 }
})
Run Code Online (Sandbox Code Playgroud)

在这种情况下,输入是具有不同类型的嵌套对象,我希望打字稿能够提示我as aDeep的类型和as的类型。foo.namestringfoo.fn() => number

我应该如何声明 的类型Flat<T, ?>

jca*_*alz 5

我必须稍微修改一下你的类型和代码,并猜测你想要做什么,但看起来这是一个你想要从映射类型进行推断的例子。不要试图描述一个Flat<>接受输入并将Nested<?>其展平以产生输出类型的类型函数,而是相反:将其视为T展平的输出类型和Nested<T>输入的类型:

// this is the same
interface Deep<T> {
  p1: T;
  p2: T;
}

// changed: for every property of T with key P and value of type T[P],
// there is a property of Nested<T> with key P and value of type Deep<T[P]>
type Nested<T> = {
  [P in keyof T]: Deep<T[P]>;
}

// output is T, input is Nested<T> and a key of Deep<>
function flat<T>(input: Nested<T>, p: keyof Deep<any>): T {
  const put = {} as T; // assert as type T
  for (let k in input)
    put[k] = input[k][p];
  return put; // added return value
}
Run Code Online (Sandbox Code Playgroud)

我们可以按照您想要的方式使用它:

const foo = flat({
  name: { p1: 'name', p2: 'name' },
  fn: { p1: () => 0, p2: () => 1 },
}, 'p2'); // example code lacked 'p1' or 'p2' argument

foo.name.charAt(0); // works
foo.fn().toFixed(0); // works
Run Code Online (Sandbox Code Playgroud)

希望有帮助;祝你好运!