Typescript

memo & function properties & Generic

首先 memo 在 react 中会被处理为一个特殊对象,memo是一个只应该被用于开发者进行传参确定的类型,其实根本不需要暴露给使用者,所以在导出时直接 as 原组件函数类型,是能够让各种导出类型问题得以解决的很好的方式:

  1. const defaultComponent = memo(FormBundle) as typeof FormBundle;

如果一个函数,需要携带额外的属性,也就是外部使用时可以通过 Function.xx 的方式进行调用,尽量使用 Object.assign 进行处理,这样可以保证类型安全:

  1. export default Object.assign(defaultComponent, {
  2. exeStrategy,
  3. });

之所以说安全,原理应该是类型的可能性被尽量枚举了,从 Object.assign 的定义中也可见一斑:image.png
按不同传参重载不同的函数体。这也是普遍的目前 ts 中处理这种可无限参数函数体的一个方案。虽然丑陋,但可用。
如果直接在 defaultComponent.xx 进行挂载则会报类型错误。因为一个结构的类型肯定是要在其实现时就必须完全实现的。但显然函数体在定义(定义同时也是实现,js不支持定义时组合,函数也没法继承)时是没法多外挂一个属性的。所以只能采用这种之后再组合从而获得新类型的方式来进行操作。
于是通过上述的两种操作,外部导出的组件也自然就可以进行正常的泛型传递了。因为 memo 的包裹,泛型参数会无法传递,通过 as 原组件,可以解决。其次通过组合的导出,在外部使用时,会推导为使用了函数体,所以泛型参数则可以传递。

  1. const defaultComponent = memo(FormBundle) as typeof FormBundle;
  2. export default Object.assign(defaultComponent, {
  3. exeStrategy,
  4. });

通过定义我们想要的导出形状,也可以验证组合后的类型是正确的:
image.png
在没有 Object.assign 的场景中也可以使用类似的 merge 方法:

  1. function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
  2. Object.keys(from).forEach((key) => {
  3. onto[key] = from[key];
  4. });
  5. return onto as T1 & T2;
  6. }

因为 Ts 目前不支持高阶泛型(泛型嵌套)。所以可以通过组件定义者枚举出所有的 enum T,外部直接传递 项,作为组件的泛型参数,也可达到类似的效果。

泛型参数作为index

image.png
https://stackoverflow.com/questions/41179474/use-object-literal-as-typescript-enum-values
T可作为 Object 的 index。但需要符合两个条件:

  1. Object本身可穷举:
    1. Object定义后不可变,Object.freeze 或直接从类型层面 as const;
  2. T 本身可穷举:
    1. T 一定是属于 Object.Keys 的子集合;

同样如果需要对非string的Key做可枚举映射,可以考虑使用Map。

如果是值类型简单的情况,或值可为联合类型的情况则可使用如下结构:
https://github.com/microsoft/TypeScript/issues/15768

  1. interface IRecord {
  2. id: number,
  3. name: string
  4. }
  5. function extract<K extends string>(data: Record<K, string>[], field: K): void {
  6. const value: string = data[0][field]; // see error below
  7. }
  8. const data: IRecord[] = [{ id: 1, name: "one" }, { id: 2, name: "two" }]
  9. extract(data, "id"); // error that id can't be used as a parameter since it's not a string
  10. extract(data, "name") // no error, expected behaviour

Structural type system
https://en.m.wikipedia.org/wiki/Structural_type_system
https://www.zhihu.com/question/314434687/answer/628101937
Ts 应该属于典型的 结构类型系统。
与鸭子类型比较的一个最大不同就是,鸭子类型是动态类型,结构类型是静态的。
所以静态的系统,需要对不同的入参进行多态处理,必须要首先保证入参穷举(定义后不可变),继而定义对不同入参的处理方式,这样才能实现完全静态。
Ts 中目前没有太完备的枚举系统及模式匹配,只能依靠 Object[T] + switch 这样的方式来实现枚举下的处理来实现静态检查。

Structural type systems[edit]

Duck typing is similar to, but distinct from, structural typing. Structural typing is a static typing system that determines type compatibility and equivalence by a type’s structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type’s structure that is accessed during run time).
The TypeScript,[6] OCaml, Scala), Go), Elm),[7] Gosu) and PureScript languages support structural typing to varying degrees.

Protocols and interfaces[edit]

Protocols and interfaces) may provide some of the benefits of duck typing, yet duck typing is distinct in not having an explicit interface defined. For example, if a third party library implements a class that cannot be modified, a client cannot use an instance of it with an interface unknown to that library even if the class does, in fact, satisfy the interface requirements. (A common solution to this problem is the Adapter pattern.) Duck typing would allow this. Again, all of an interface must be satisfied for compatibility.

Templates or generic types[edit]

Template, or generic functions or methods apply the duck test in a static typing context; this brings all the advantages and disadvantages of static versus dynamic type checking in general. Duck typing can also be more flexible in that only the methods actually called at runtime need to be implemented, while templates require implementations of all methods that can not be proven unreachable at compile time.
Languages like Python, Java and Objective-C are examples of duck typing because it is possible in them to construct new types in runtime via reflection) and inspect whether these objects implement certain methods. On the other hand, there are languages that rely on compile-time metaprogramming techniques (like C++ and its template system) and thus do not fit into the category of duck typing; instead, at some point in the compilation pipeline, all placeholder types become substituted with some concrete types specified in a particular instantiation. Even though certain type erasure is possible in them, runtime inspection is limited.

Js

Intl

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl
统一处理时间字符串用这个感觉还可以,并且也能兼容到ie11
image.png