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

问题描述

我想在不使用 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 中进行?

解决方法

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",testFunction(e) {
        e.toExponential(2) // ok
        e.indexOf('e') // error
    }
}

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...