打字稿:数组元素的类型推断

时间:2021-06-24 09:00:42

标签: typescript typescript-generics

我想在不使用 T 的情况下获得以下行为:

interface Test<T> {
  sameField: string;
  test: T
  testFunction: (e: T) => void
}

const array: Array<Test</*something something*/_>> = [
  {
    sameField: "foo",
    test: 1,
    testFunction: (e) => {
      e.toExponential(2) // Should be Valid
      e.indexOf('e') // Should be Invalid
    }
  },
  {
    sameField: "bar",
    test: "baz",
    testFunction: (e) => {
      e.indexOf('e') // Is Valid
      e.toExponential(2) // Should be Invalid
    }
  }
]

它背后的想法只是告诉 Typescript“让数组元素自己处理它们的输入”的一种方式。 是否只能在 Typescript 中进行?

1 个答案:

答案 0 :(得分:1)

TS 无法自行推断出此类数据结构中的 e 参数。

这里有多种选择。

第一

预先定义您的 test 属性:

type Main = {
    foo: string;
    bar: number;
};

type Validator<T extends keyof Main> = {
    test: T;
    isValid: (value: Main[T]) => boolean;
};

type Values<T> = T[keyof T]

type MainValidationRule = Values<{
    [P in keyof Main]: {
        test: P;
        isValid: (value: Main[P]) => boolean;
    }
}>

const validators: Array<MainValidationRule> = [
    { test: 'foo', isValid: (value/* infered to stirng */) => true },
    { test: 'bar', isValid: (value/* infered to number */) => true }
]

第二

interface Test<T> {
    field: string;
    test: T
    fn: (e: T) => void
}

const builder = <Test, Field>(test: Test, field: Field, fn: (e: Test) => any) => ({
    field,
    test,
    fn
})

const array = [builder(2, 'hello', (e/**infered to number */) => 42)]

Here,在我的博客中,您可以找到有关使用和键入回调的更多信息

还有一种方法可以做到:

interface Foo {
    sameField: "foo",
    test: 1,
    testFunction(e: this['test']): void
}

const x: Foo = {
    sameField: "foo",
    test: 1,
    testFunction(e) {
        e.toExponential(2) // ok
        e.indexOf('e') // error
    }
}

但您可能已经注意到,您应该预先声明您的 sameFieldtest

有更多选择可以做到,但我相信这将是一种开销