Skip to content
This repository has been archived by the owner on Apr 7, 2024. It is now read-only.

feat: 修改 proto TS 类型,添加 proto.extends #14

Merged
merged 1 commit into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 17 additions & 9 deletions src/biz/utils/proto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ function proto(baseRecord: any, ensureArray: boolean | 'auto' = 'auto') {
return process(arg)
}
}

// @ts-ignore
factory[factorySymbol] = true

factory.extends = (extRecord: any) => {
const extFactory = proto(extRecord, ensureArray)
return (arg: any) => factory(extFactory(arg))
}

return factory
}

Expand Down Expand Up @@ -71,23 +77,25 @@ proto.notNull[factorySymbol] = true
proto.object = (baseRecord: any) => proto(baseRecord, false)
proto.array = (baseRecord: any) => proto(baseRecord, true)

export type DeepPartial<T> = T extends object
? {
[key in keyof T]?: DeepPartial<T[key]>
}
: T
type SameKeysWith<T> = T extends object ? { [key in keyof T]?: any } : T

export type Proto<T> = (v: DeepPartial<T>) => T
interface ObjectProto<T> {
(v: SameKeysWith<T>): T
extends(ext: SameKeysWith<T>): ObjectProto<T>
}

export type ArrayProto<T> = (items: DeepPartial<T>[]) => T[]
interface ArrayProto<T> {
(items: SameKeysWith<T>[]): T[]
extends(extRecord: SameKeysWith<T>): ArrayProto<T>
}

export interface ProtoStatic {
string(v: string): string
number(v: number): number
notNull<T = any>(v: any): T

object<O extends object = any>(obj: { [key in keyof O]?: any }): Proto<O>
array<T extends object = any>(baseRecord: { [key in keyof T]?: any }): ArrayProto<T>
object<O extends object = any>(base: SameKeysWith<O>): ObjectProto<O>
array<T extends object = any>(base: SameKeysWith<T>): ArrayProto<T>

readonly empty: unique symbol
}
Expand Down
43 changes: 41 additions & 2 deletions stories/tools/proto.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'

# proto

在实际开发中过程中,一个表格可能包含了大量维度和指标(在盒马内部,50+ 列的明细表格十分常见),此时为表格的书写对应的列配置就需要花费我们大量的时间。大部分情况下,不同的列往往具有相同的宽度、相同的对齐方向、相同的格式化渲染方法,避免相同配置重复声明,可以有效减少开发工作量。`ali-react-table/biz` 导出了 `proto` 来简化这些重复配置的书写。
在实际开发中过程中,一个表格可能会包含大量维度和指标(在盒马内部,超过 50 列的表格十分常见),列配置的书写工作量会很大。这其中很多的列往往具有相同的宽度、对齐方向或是类似的格式化方法,重复配置较多。`ali-react-table/biz` 导出了 `proto` 来简化这些重复配置的书写,有效减少列配置的工作量

注:本页文档中,「原型」指的是使用 proto 创建出来的函数,而不是指 JavaScript 中的函数原型。

Expand Down Expand Up @@ -73,7 +73,7 @@ const columns = columnProto([
// [
// { code: 'code-1', width: 120, align: 'right', features: { defaultVisible: true } },
// { code: 'code-2', width: 120, align: 'right', features: { defaultVisible: false } },
// { code: 'code-3', width: 200, align: 'right', features: { defaultVisible: true, sortable: true } },
// { code: 'code-3', width: 120, align: 'right', features: { defaultVisible: true, sortable: true } },
// ]
```

Expand All @@ -97,3 +97,42 @@ const columns = columnProto([
```

此外,`proto.notNull` 用于确保输入参数中某个字段不能为 null/undefine。

## 原型的继承

通过 `proto.object` / `proto.array` 生成的对象上有一个 extends 的方法,可以在已有的原型基础上生成新的原型。

```js
const column = proto.object({ width: 120, align: 'left' })
const alignRightColumn = column.extends({ align: 'right' })
const wideColumn = column.extends({ width: 200 })

const col1 = alignRightColumn({}) // { align: "right", width: 120 }

const col2 = wideColumn({}) // { width: 200, align: "left" }
```

用继承的原型生成最终的对象时,会先根据继承的配置处理数据,然后调用基础的配置处理数据。

## `proto.empty`

`proto.empty` 是一个特殊的 symbol,其作用是从结果中移除特定字段。

```js
const columnProto = proto.array({
width: 120,
align: 'right',
features: proto.object({ defaultVisible: true }),
})

const columns = columnProto([
{ code: 'code-1' },
{ code: 'code-2', align: proto.empty },
{ code: 'code-3', features: proto.empty },
])
// [
// { code: 'code-1', width: 120, align: 'right', features: { defaultVisible: true } },
// { code: 'code-2', width: 120, features: { defaultVisible: true } },
// { code: 'code-3', width: 120, align: 'right' },
// ]
```