我有一个组件,它有3个props :toValue,fromValue,children.前两个是可选的,但如果指定了其中一个,则还必须指定另一个.children属性是一个具有inputProps参数的函数,如果指定,它应该等于toValue函数的返回类型(TInputValue)或TStateValue.

我编写了以下代码,但我不明白为什么在指定了toValue函数的情况下,inputPropsany.如何修复它?

interface IP<T> {
  value: T
  onChange: (value: T) => void
}
interface A<TStateValue> {
  toValue?: never
  fromValue?: never
  children: (inputProps: IP<TStateValue>) => null
}
interface B<TStateValue, TInputValue>  {
  toValue: (value: TStateValue) => TInputValue
  fromValue: (value: TInputValue) => TStateValue
  children: (inputProps: IP<TInputValue>) => null
}
type C<TStateValue, TInputValue> =
  | A<TStateValue>
  | B<TStateValue, TInputValue>

const propsWithoutToValue: C<number, string> = {
  children: (inputProps) => null, // `inputProps` is `IP<number>`. Nice!
}
const propsWithToValue: C<number, string> = {
  toValue: (value) => value.toString(), // The return type is a `string`, so the `inputProps` must be `IP<string>`
  fromValue: (value) => Number(value),
  children: (inputProps) => null, // `inputProps` is any, but must be `IP<string>`. How to fix it?
}

我已经为我正在努力解决的问题创建了回购:https://github.com/oxilor/form-types

推荐答案

快速解决方案:

interface IP<T> {
  value: T
  onChange: (value: T) => void
}
interface A<TStateValue> {
  type:"A",
  children(inputProps: IP<TStateValue>, a:1) : null
}
interface B<TStateValue, TInputValue>  {
  type: "B",
  toValue: (value: TStateValue) => TInputValue
  fromValue: (value: TInputValue) => TStateValue
  children(inputProps: IP<TInputValue>) : null
}

type C<TStateValue, TInputValue> =
  | B<TStateValue, TInputValue>
  | A<TStateValue>

const propsWithoutToValue: C<number, string> = {
  type: "A",
  children: (inputProps) => null,
  //          ^?
}
const propsWithToValue: C<number, string> = {
  type: "B",
  toValue: (value) => value.toString(), 
  fromValue: (value) => Number(value),
  children: (inputProps) => null,
  //            ^?
}

enter image description here

playground

//=

A点:如果您try 将2个函数与不同的参数类型合并,则参数类型为any

enter image description here

important update: 100

B点:TypeScrip认为您try 联合2个函数的原因是,具有相同对象属性的联合函数的行为方式与两个函数的联合相同

enter image description here

这基本上意味着{b:((a:1)=>void)} | {b:((a:number)=>void)}是字面意义上的{b:((a:1)=>void) | ((a:number)=>void)}

有几件事我无法解释:

  1. A点和B点所示行为背后的理由(目的是什么)
  2. 它看起来像是有区别联合(或通常的联合)不能正确处理函数类型(或本能地不能工作)
  3. 点A不适用于prosWithoutToValue,但适用于prosWithToValue,很可能是点2的后效

Typescript相关问答推荐

在Angular中注入多个BrowserModules,但在我的代码中只有一个

如何使用一个字段输入对象,其中每个键只能是数组中对象的id属性,而数组是另一个字段?

带switch 的函数的返回类型的类型缩小

打印脚本中的动态函数重载

接口中函数的条件参数

使用2个泛型类型参数透明地处理函数中的联合类型

TypeScrip:来自先前参数的参数中的计算(computed)属性名称

将带点的对象键重新映射为具有保留值类型的嵌套对象

常量类型参数回退类型

TypeScrip错误:为循环中的对象属性赋值

ANGLE订阅要么不更新价值,要么不识别价值变化

为什么S struct 类型化(即鸭子类型化)需要非严格类型联合?

对有效枚举值的常量字符串进行常规判断

基于未定义属性的条件属性

Typescript .根据枚举输入参数返回不同的对象类型

有没有一种更好的方法来存储内存中的数据,而不是在类型脚本中使用数组和基于索引的函数?

导航链接不触发自定义挂钩

类型为 `(callback: (...args: T) => void, params: T)` 的函数的泛型

node_modules/@newrelic/native-metrics:命令失败. node_modules/couchbase:命令失败.退出代码:127

如何解决 Angular 中的 ts(18048) 错误