如何推断组件的 @Input 的正确类型

Jos*_*man 5 strong-typing typescript angular

我正在寻找一种方法来推断组件的 @Inputs 的正确类型。到目前为止,我只能@Input使用以下命令来定位属性:

// Method in a service
setComponentInputs<T> (props: { [key in keyof T]?: any }) {
   console.log(props);
}
Run Code Online (Sandbox Code Playgroud)

但正如您所看到的,类型仍然是any
另外,当前的方法允许针对组件内的所有内容,包括方法(例如 OnInit),但我不太确定是否有一个技巧可以仅针对 @Inputs。

让我为您提供更多背景信息,这是一个标准的 Angular 组件:

@Component({
  selector: '',
  templateUrl: './foo.component.html',
  styleUrls: ['./foo.component.scss']
})
export class FooComponent implements OnInit {
  @Input() myProp: string;
  @Input() otherProp: CustomProp;

  constructor() {}

  ngOnInit() {
  }
}
Run Code Online (Sandbox Code Playgroud)

这个想法是setComponentInputs(props)在限制 props 参数以匹配组件@Inputs属性的同时进行调用

// this one should compile
myService.setComponentInputs<FooComponent>({myProp: 'Hello there!'});

// this one should raise an error (because the type of myProp is string)
myService.setComponentInputs<FooComponent>({myProp: 123});

// this one should raise an error (because the referenced property don't even exist)
myService.setComponentInputs<FooComponent>({newProp: 'Hello!'});
Run Code Online (Sandbox Code Playgroud)

编辑 1:我找到了一种使用映射类型来克服主要问题的方法

// Method in a service
setComponentInputs<T> (props: { [P in keyof T]?: T[P] }) {
   console.log(props);
}
Run Code Online (Sandbox Code Playgroud)

但随后 @andrei 指出了一种不同且更简单的方法:

// Method in a service
setComponentInputs<T> (props: Partial<T>) {
   console.log(props);
}
Run Code Online (Sandbox Code Playgroud)

剩下的部分将是如何仅允许属性而排除函数(例如 OnInit)

// this one should raise an error (because ngOnInit is a Function)
myService.setComponentInputs<FooComponent>({ngOnInit: () => {});
Run Code Online (Sandbox Code Playgroud)