例如,我有一些界面:

interface Foo {
  bar: string;
  baz: (param: any) => void;
}

和一个对象:

const test = { 
  bar: 'id', 
  baz: (param) => console.log(param.id),
};

在不使用映射类型的情况下,如何强制TypeScrip将bar值用作paramkey类型?所以我想要像这样的东西:

interface Foo<J> {
  bar: J;
  baz: (param: {[key: J]: any}) => void;
}

和一个对象:

const test = { 
  bar: 'id', 
  baz: ({id}) => console.log(id), // <== here should typescript allow only the id property
};

我知道我可以使用映射类型来实现该行为,但这不是我在这里想要的

推荐答案

Typescript 中没有specificFoo是这样工作的.您可以得到的最接近的结果是将您的需求表示为generic类型Foo<K>,其中K对应于bar属性.它与您所拥有的非常接近,只是您试图使用index signature {[key: K]: any},这对于泛型是无效的.相反,您需要mapped type {[P in K]: any}:

interface Foo<K extends PropertyKey> {
  bar: K;
  baz: (param: { [P in K]: any }) => void;
}

不幸的是,编译器无法将类型参数推断为泛型类型,因此您不能编写const test: Foo<infer> = {⋯}const test: Foo<?> = {⋯}const test: Foo = {⋯}或类似的代码.不过,当您调用泛型functions时,编译器can会推断类型参数,因此您可以创建一个帮助器函数:

const asFoo = <K extends PropertyKey>(foo: Foo<K>) => foo;

然后像const test = asFoo({⋯})一样使用它:

const test = asFoo({
  bar: 'id',
  baz: ({ id }) => console.log(id), // okay
});

const test2 = asFoo({
  bar: 'id',
  baz: ({ oops }) => console.log(oops), // error 
});

Playground link to code

Typescript相关问答推荐

如何使用Generics保留构造函数的类型信息?

如何从具有给定键列表的对象类型的联合中构造类型

TS不推断类型在条件判断后具有属性'

在映射类型中用作索引时,TypeScrip泛型类型参数无法正常工作

如何在TypeScript中将一个元组映射(转换)到另一个元组?

TypeScrip:逐个 case Select 退出noUncheck kedIndexedAccess

Material UI / MUI系统:我如何告诉TypeScript主题是由提供程序传递的?

<;T扩展布尔值>;

限制返回联合的TS函数的返回类型

如何在Vue中使用Enum作为传递属性的键类型?

基于泛型的条件接口键

是否可以强制静态方法将同一类型的对象返回其自己的类?

ANGLE NumberValueAccessor表单控件值更改订阅两次

当数组类型被扩展并提供标准数组时,TypeScrip不会抱怨

为什么特定的字符串不符合包括该字符串的枚举?

声明遵循映射类型的接口

作为函数参数的联合类型的键

如果判断空值,则基本类型Gaurd不起作用

可以用任意类型实例化,该类型可能与

有没有一种方法可以防止我的组件包在其中安装样式组件'; node 模块中的s目录