如何从另一个属性推断类型

huangapple go评论48阅读模式
英文:

How to infer type from another property

问题

以下是您要翻译的代码部分:

I'm typing a basic migration utility – an object that has properties `up()` and `down()`. When committing a migration I'm saving the returned data from the `up()` function and then passing it as an argument to the `down()` function, like this:

const myMigration: Migration<number[]> = {
  async up() {
    return [1, 2, 3];
  },
  async down(data) {
    data.forEach(number => console.log(number)); // 1, 2, 3
  },
};

So far, I've defined the Migration type like this:

type Migration<T = void> = {
  up(): Promise<T>
  down(data: T): Promise<void>
}
type Migration<T = void> = {
  up(): Promise<T>
  down<U extends T = T>(data: U): Promise<void>
}
type Migration<T = void> = {
  up(): Promise<T>
  down(data: Awaited<ReturnType<Migration["up"]>>): Promise<void>
}

Desired result:

const myMigration: Migration = {
  async up() {
    return [1, 2, 3];
  },
  async down(data) {
    // yay, type of data is inferred
    data.forEach(number => console.log(number)); // 1, 2, 3
  },
};

[TypeScript playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAsglgcwE4ENhwPYDsA8AVKAXigDcM4ATAPiKgG8AoKZqAVzAAoBKALigAUkGALZwAzhHxUmLChgDuWDjJay0KPgEF5KOMAgUcAJQjBWSLHnCT4yNJlx4qAbQDk7VwF0q01bwFCohI4ZJTSAL4MDADG2GLAUKJ26Nh8tqgpWLSMqihiIFjRbJxc9CqqUEim5lnOAIwANFAATE0AzJ7l4Q3leQVFcoocFOqlORXMI8AoAHQAZhhIAKIo0QAWHBxYrMKlhDSxWGIYADYQMycYCFs7XFwA3F0M4UA


希望这能帮助您。如果您需要进一步的帮助,请随时告诉我。

<details>
<summary>英文:</summary>

I&#39;m typing a basic migration utility – an object that has properties `up()` and `down()`. When committing a migration I&#39;m saving the returned data from the `up()` function and then passing it as an argument to the `down()` function, like this:

```typescript
const myMigration: Migration&lt;number[]&gt; = {
  async up() {
    return [1, 2, 3];
  },
  async down(data) {
    data.forEach(number =&gt; console.log(number)); // 1, 2, 3
  },
};

So far, I've defined the Migration type like this:

type Migration&lt;T = void&gt; = {
  up(): Promise&lt;T&gt;
  down(data: T): Promise&lt;void&gt;
}

The current problem is that I have to explicitly define the type, but rather I would like to have the type of the down() data argument inferred from the awaited return type of up().

Here are some of my failed attempts:

// doesn&#39;t work

type Migration&lt;T = void&gt; = {
  up(): Promise&lt;T&gt;
  down&lt;U extends T = T&gt;(data: U): Promise&lt;void&gt;
}
// doesn&#39;t infer type from the same instance

type Migration&lt;T = void&gt; = {
  up(): Promise&lt;T&gt;
  down(data: Awaited&lt;ReturnType&lt;Migration[&quot;up&quot;]&gt;&gt;): Promise&lt;void&gt;
}

Desired result:

const myMigration: Migration = {
  async up() {
    return [1, 2, 3];
  },
  async down(data) {
    // yay, type of data is inferred
    data.forEach(number =&gt; console.log(number)); // 1, 2, 3
  },
};

TypeScript playground

答案1

得分: 1

你可以使用一个创建函数,它可以推断类型,例如:

type Migration<T> = {
    up(): Promise<T>
    down(
        data: Awaited<ReturnType<Migration<T>['up']>>
    ): Promise<void>
}

function createMigration<T>(mig: Migration<T>) {
    return mig;
}

const migration = createMigration({
    async up() {
        return [1, 2, 3]
    },
    async down(data) {
        data.forEach((num) => console.log(num));
    }
})

Playground Example

英文:

you could use a create function that can infer the type, e.g.

type Migration&lt;T&gt; = {
    up(): Promise&lt;T&gt;
    down(
        data: Awaited&lt;ReturnType&lt;Migration&lt;T&gt;[&#39;up&#39;]&gt;&gt;
    ): Promise&lt;void&gt;
}

function createMigration&lt;T&gt;(mig: Migration&lt;T&gt;) {
    return mig;
}

const migration = createMigration({
    async up() {
        return [1, 2, 3]
    },
    async down(data) {
        data.forEach((num) =&gt; console.log(num));
    }
})

Playground Example

答案2

得分: 0

以下是翻译好的部分:

"It's seems like the only way to achieve this is using factory with generic paramert. Here's an example:

type Migration<T> = {
  up(): Promise<T>;
  down(data: T): Promise<void>
}

const createMigration = <T>(config: Migration<T>) => config

const myMigration = createMigration({
  async up() {
    return [1,2,3]
  },
  async down(data) {
    // data is infered from the `up` method
  }
})
```"

<details>
<summary>英文:</summary>

It&#39;s seems like the only way to achieve this is using factory with generic paramert. Here&#39;s an example:

type Migration<T> = {
up(): Promise<T>;
down(data: T): Promise<void>
}

const createMigration = <T,>(config: Migration<T>) => config

const myMigration = createMigration({
async up() {
return [1,2,3]
},
async down(data) {
// data is infered from the up method
}
})


</details>



huangapple
  • 本文由 发表于 2023年2月18日 19:18:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492973.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定