简体   繁体   English

打字稿定义 - 嵌套函数

[英]Typescript Definitions - nested functions

As listed below, let's say we have:如下所列,假设我们有:

  1. a function r that combines multiple tasks together将多个任务组合在一起的函数r
  2. and a function o that returns a shape like when(cb).map(cb)和一个函数o返回一个像when(cb).map(cb)这样的形状

every callback passed to when or map should always take these 3 arguments: S, A, C where S and C are defined in r and A is defined in o .传递给whenmap每个回调都应始终采用以下3参数: S, A, C ,其中SCr中定义, Ao定义。

here is a link to the typescript playground which also shows the error I am getting.这是打字稿游乐场的链接,它也显示了我遇到的错误。

My question is: How can I get a typesafe declaration?我的问题是:如何获得类型安全声明?

type Task<S, A, C> = <AA extends A>(s: S, a: AA, c: C) => any;
type Fn<S, A, C> = (s: S, a: A, c: C) => any;

const r = <S, C>() => ({
  tasks: (...tasks: Task<S, any, C>[]) => null,
});

const o = <T, A = { prop: T }>(type: T) => ({
  when: <S, C>(fp: Fn<S, A, C>) => ({
    map: <SS extends S, CC extends C>(fn: Fn<SS, A, CC>): Task<SS, A, CC> => (
      (s: SS, a: A, c: CC): any => (
        fp(s, a, c) ? fn(s, a, c) : s
      )
    ),
  }),
});

const result = r<2, 7>().tasks(
  o(44) // expect: cb(2, 44, 7)
    .when((s, a, c) => s + a.prop + c)
    .map((s, a, c) => s + a.prop + c),

  o(78) // expect: cb(2, 78, 7)
    .when((s, a, c) => s + a.prop + c)
    .map((s, a, c) => s + a.prop + c),

  // etc...
  // callback provided to `.map` is typesafe,
  // callback provided to `.when` is not,
);

<code>when(cb)</code> 的 <code>S</code> 和 <code>C</code> 的类型丢失

As you can see, the callback provided to when is not typesafe : Params S and C are lost .如您所见,提供给when的回调不是类型安全的Param SC丢失

Hmm, among other problems, it looks like you want some contextual type inference that the language doesn't provide for.嗯,除其他问题外,您似乎想要一些语言没有提供的上下文类型推断 Here is how I would recommend typing things:以下是我建议键入的内容:

type Fn<S, A, C> = (s: S, a: A, c: C) => any;

// allow tasks to be an array of Fn<S, any, C> 
const r = <S, C>() => ({
  tasks: <FF extends Fn<S, any, C>[]>(...tasks: FF) => null,
});
// it is concerning that S and C must be explicitly specified
// when calling r(); not sure how you will hook that up to runtime

// only make types generic if they need to be, 
// and declare close to their uses if you want them to be inferred
const o = <T>(type: T) => ({
  when: <S, C>(fp: Fn<S, { prop: T }, C>) => ({
    map: (fn: Fn<S, { prop: T }, C>) => (s: S, a: { prop: T }, c: C): any =>
      fp(s, a, c) ? fn(s, a, c) : s,
  }),
});

const result = r<2, 7>().tasks(
  o(44) // expect: db(2, 44, 7)
    // you need to annotate the s and c parameters in when().
    // The compiler does not try to infer S and C in o(44).when() contextually 
    // from the contextual parameter type of r<2.7>().tasks().
    .when((s: 2, a, c: 7) => s + a.prop + c)
    .map((s, a, c) => s + a.prop + c),

  o(78) // expect: db(2, 78, 7)        
    // alternatively you can specify S and C manually:
    .when<2, 7>((s, a, c) => s + a.prop + c)
    .map((s, a, c) => s + a.prop + c),
  // etc...
);

You've changed your definitions since I worked on this, so the following might not match up exactly with what you posted.自从我从事此工作以来,您已经更改了定义,因此以下内容可能与您发布的内容不完全匹配。 In short:简而言之:

  • Make r().tasks() take an array (possibly a tuple ) of Fn<S, any, C> values, so the fact that the second task's A is not the same as the first won't cause an error.使r().tasks()采用Fn<S, any, C>值的数组(可能是元组),因此第二个任务的A与第一个任务的A这一事实不会导致错误。

  • Don't have a generic T and also a generic A = {prop: T} .没有通用T和通用A = {prop: T} I'm guessing A is not meant to be independent from T and you are trying to use a default type parameter to represent some kind of assignment, but it doesn't really work that way.我猜A并不意味着独立于T并且您正在尝试使用默认类型参数来表示某种赋值,但它并没有真正起作用。 Instead, just use T and then replace all instances of A with {prop: T} .相反,只需使用T然后用{prop: T}替换A所有实例。

  • Only have as many generic types as you need and as close to the desired inference place as possible.只拥有您需要的尽可能多的泛型类型,并尽可能靠近所需的推理位置。 I've moved S and C to o().when .我已将SC移至o().when

  • Finally, contextual typing from the parameter of r<2.7>().tasks() to the values of S and C in o().when() does not occur.最后,不会发生从r<2.7>().tasks()o().when()SC的值的上下文类型。 The compiler probably doesn't even try to do it, since the inference would have to happen across multiple levels of function call.编译器甚至可能不会尝试这样做,因为推断必须跨多个函数调用级别发生。 The only way to deal with that seems to be to re-specify S and C , either by annotating the s and c parameters of the callback passed to o().when() , or by calling o().when<2,7>() .解决这个问题的唯一方法似乎是重新指定SC ,或者通过注释传递给o().when()的回调的sc参数,或者通过调用o().when<2,7>()

Hope that helps point you in the right direction.希望能帮助您指明正确的方向。 Good luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM