Giter VIP home page Giter VIP logo

Comments (13)

Mrlgm avatar Mrlgm commented on May 18, 2024 32
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never

// 测试用例
type U0 = UnionToIntersection<string | number> // never
type U1 = UnionToIntersection<{ name: string } | { age: number }> // { name: string; } & { age: number; }

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types

from awesome-typescript.

Nygma0058 avatar Nygma0058 commented on May 18, 2024 14
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never

将这个方法拆成两部分来看,(U extends any ? (k: U) => void : never)是第一部分,extends (k: infer I) => void ? I : never是第二部分

  • 先看第一部分,TS中如果泛型后跟extends且这个泛型在实际传值是联合类型,则会遍历这个联合类型,取出联合类型中的每个具体类型做实际操作,最后返回每个类型的结果的联合类型
    U=string|number举例,第一部分实际上做的的操作是(string extends any ? (k:string) => void :never) | (number extends any ? (k:number) => void :never),简化之后的结果就是((k:string)=>void)|((k:number)=>void),这是两个函数类型的联合类型
  • 再看第二部分,利用了infer的函数参数类型推断,翻译一下就是如果想要找出一个函数,使它满足一定条件后能被((k:string)=>void)|((k:number)=>void)赋值,那么这个函数一定是(k:string&number)=>void,从而推得函数参数类型是string&number作为结果

from awesome-typescript.

yubaoquan avatar yubaoquan commented on May 18, 2024 5

看了代码还是有点不懂哈 [流泪] 可以麻烦大佬再说细一点嘛...

尝试解读3楼大佬的写法:

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never

如果U是never类型, 直接返回never类型;

否则声明一个以U为入参类型的函数类型A, 即(k: U) => void, 此函数继承自以I类型为入参的函数类型B, 即(k: infer I) => void.

如果A能继承B, 那么入参类型I一定包含所有U的类型, 所以返回的I就是所有U的交叉类型;

否则返回never
@TheMaximumPotential

from awesome-typescript.

zhaoxiongfei avatar zhaoxiongfei commented on May 18, 2024 1
// 实现一个 UnionToIntersection 工具类型,用于把联合类型转换为交叉类型。具体的使用示例如下所示:

type UnionToIntersection<U> = (U extends U ? (arg: U) => any: never) extends (arg: infer T) => any
  ? T
  : never;

// 测试用例
type U0 = UnionToIntersection<string | number> // never
type U1 = UnionToIntersection<{ name: string } | { age: number }> // { name: string; } & { age: number; }

利用联合类型在 extends 的时自动分发,在利用函数参数类型逆变,从而实现了联合类型到交叉类型的转变。

from awesome-typescript.

zhaoxiongfei avatar zhaoxiongfei commented on May 18, 2024
/**
 * 将联合类型转为对应的交叉函数类型
 * @template U 联合类型
 */
type UnionToInterFunction<U> = (U extends any ? (k: () => U) => void : never) extends (
  k: infer I,
) => void
  ? I
  : never;

/**
 * 获取联合类型中的最后一个类型
 * @template U 联合类型
 */
type GetUnionLast<U> = UnionToInterFunction<U> extends { (): infer A } ? A : never;

/**
 * 在元组类型中前置插入一个新的类型(元素);
 * @template Tuple 元组类型
 * @template E 新的类型
 */
type Prepend<Tuple extends any[], E> = [E, ...Tuple];

/**
 * 联合类型转元组类型;
 * @template Union 联合类型
 * @template T 初始元组类型
 * @template Last 传入联合类型中的最后一个类型(元素),自动生成,内部使用
 */
type UnionToTuple<Union, T extends any[] = [], Last = GetUnionLast<Union>> = {
  0: T;
  1: UnionToTuple<Exclude<Union, Last>, Prepend<T, Last>>;
}[[Union] extends [never] ? 0 : 1];

type TupleToIntersection<T extends Array<any>> = T extends [infer F, ...infer U]
  ? U extends []
    ? F
    : F & TupleToIntersection<U>
  : never;

type UnionToIntersection<U> = TupleToIntersection<UnionToTuple<U>>;

// 测试用例
type U0 = UnionToIntersection<string | number>; // never
type U1 = UnionToIntersection<{ name: string } | { age: number }>; // { name: string; } & { age: number; }

from awesome-typescript.

TheMaximumPotential avatar TheMaximumPotential commented on May 18, 2024

看了代码还是有点不懂哈 [流泪] 可以麻烦大佬再说细一点嘛...

from awesome-typescript.

wang-yi-bit64 avatar wang-yi-bit64 commented on May 18, 2024
/**
 * 将联合类型转为对应的交叉函数类型
 * @template U 联合类型
 */
type UnionToInterFunction<U> = (U extends any ? (k: () => U) => void : never) extends (
  k: infer I,
) => void
  ? I
  : never;

/**
 * 获取联合类型中的最后一个类型
 * @template U 联合类型
 */
type GetUnionLast<U> = UnionToInterFunction<U> extends { (): infer A } ? A : never;

/**
 * 在元组类型中前置插入一个新的类型(元素);
 * @template Tuple 元组类型
 * @template E 新的类型
 */
type Prepend<Tuple extends any[], E> = [E, ...Tuple];

/**
 * 联合类型转元组类型;
 * @template Union 联合类型
 * @template T 初始元组类型
 * @template Last 传入联合类型中的最后一个类型(元素),自动生成,内部使用
 */
type UnionToTuple<Union, T extends any[] = [], Last = GetUnionLast<Union>> = {
  0: T;
  1: UnionToTuple<Exclude<Union, Last>, Prepend<T, Last>>;
}[[Union] extends [never] ? 0 : 1];

type TupleToIntersection<T extends Array<any>> = T extends [infer F, ...infer U]
  ? U extends []
    ? F
    : F & TupleToIntersection<U>
  : never;

type UnionToIntersection<U> = TupleToIntersection<UnionToTuple<U>>;

// 测试用例
type U0 = UnionToIntersection<string | number>; // never
type U1 = UnionToIntersection<{ name: string } | { age: number }>; // { name: string; } & { age: number; }

好像有问题 ts @zhaoxiongfei
与类型“UnionToTuple<U, [], GetUnionLast>”和“any[]”相比,堆栈深度过高。ts(2321)

from awesome-typescript.

rookiecdn avatar rookiecdn commented on May 18, 2024

(k: U) => void : never) extends (k: infer I) => void ? I

求大佬讲解一下思路 文档看了 但是并没有找到什么灵感

from awesome-typescript.

a572251465 avatar a572251465 commented on May 18, 2024

export default {}

// 实现一个 UnionToIntersection 工具类型,用于把联合类型转换为交叉类型。具体的使用示例如下所示
type UnionToIntersection = (U extends any ? (k: U) => any : never) extends (k: infer U) => any ? U : never

// 测试用例
type U0 = UnionToIntersection<string | number> // never
type U1 = UnionToIntersection<{ name: string } | { age: number }> // { name: string; } & { age: number; }

from awesome-typescript.

dentm avatar dentm commented on May 18, 2024
Likewise, multiple candidates for the same type variable in contra-variant positions causes an intersection type to be inferred:

type Bar<T> = T extends { a: (x: infer U) => void; b: (x: infer U) => void }
  ? U
  : never;
type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // string & number

from awesome-typescript.

lq-math-dog avatar lq-math-dog commented on May 18, 2024

// 补充说明 协助理解
// T extends U ? X : Y T 的类型为 A|B|C 会被解析为 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)
// 条件类型定义: T extends U ? X : Y; 可以简单理解为三目运算
// 分布式条件类型定义: 被检测类型是一个联合类型的时候,该条件类型被称之为分布式条件类型. 即 T 的类型为 A|B|C
// ****
// 在协变的位置上,同一类型变量的多个候选类型会被推断为联合类型
type Foo1 = T extends { a: infer U, b: infer U } ? U : never;
type T10 = Foo1<{ a: string, b: string }>;// string
type T11 = Foo1<{ a: string, b: number }>;//string | number
// 在逆变的位置上,同一类型多个候选类型会被推断为交叉类型 , 逆变现象只会在函数类型中的函数参数上出现。
type Bar1 = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
type T20 = Bar1<{ a: (x: string) => void, b: (x: string) => void }>; //string
type T21 = Bar1<{ a: (x: string) => void, b: (x: number) => void }>; //string & number
// ****

from awesome-typescript.

duKD avatar duKD commented on May 18, 2024

第二部分 属于 显示 传 类型 不会 触发联合类型 条件判断时 分布式计算 只会采用 非分步式计算 就是楼主说的推断情况

from awesome-typescript.

SweeperDuan avatar SweeperDuan commented on May 18, 2024
type UnionToIntersection<U> =
  (
    U extends any
    ? (k: U) => void
    : never
  ) extends (k: infer P) => void ? P : never

from awesome-typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.