Skip to content

Commit

Permalink
fix(eslint-config): @keep-dto support handle Utility Types & Custom U…
Browse files Browse the repository at this point in the history
…tility Types
  • Loading branch information
ddosakura committed Oct 28, 2024
1 parent 61f6b0c commit 53fc110
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 56 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-dolphins-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ddosakura/eslint-config": patch
---

@keep-dto support handle Utility Types & Custom Utility Types
44 changes: 44 additions & 0 deletions src/commands/keep-dto.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Keep the DTO(data transfer object) interface normalized.
```ts
interface A {
a: 1
b: 1 | 2
}
```

Expand All @@ -21,6 +22,7 @@ Will be converted to:
/// keep-dto
interface A {
a: number
b: 1 | 2
}
```

Expand Down Expand Up @@ -107,3 +109,45 @@ interface A {
b: number
}
```

#### TSUnionType & TSIntersectionType

```ts
export type A = 1 | { a_b: 2 } & 3
```
Will be converted to:
```ts
// @keep-dto
export type A = 1 | { aB: number } & 3
```
```ts
// @keep-dto { "literal": "all", "ignores": ["0", "1.0.a_b"] }
export type A = 1 | { a_b: 2 } & number
```
#### Utility Types & Custom Utility Types
buildin:
- Array
- Partial
- Required
- Readonly
- NonNullable
- Pick
- Omit
- Record
custom:
```ts
type X<A, B, C> = A | B | C
// @keep-dto { "utilities": { "Awaited": 0, "Promise": 0, "X": [0, 2] } }
export interface A {
a: Awaited<Promise<{ a: number }>>
b: X<{ a: number }, { b: 2 }, { c: number }>
}
```
114 changes: 60 additions & 54 deletions src/commands/keep-dto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,58 +466,64 @@ run(
`,
errors: ['command-fix'],
},
// {
// description: 'Utility Types #1: Partial&Required&Readonly&NonNullable',
// code: $`
// // @keep-dto
// export interface A {
// a: Partial<{ a: 1 }>
// b: Required<{ a?: 1 }>
// c: Readonly<{ a: 1 }>
// d: NonNullable<{ a: 1 } | null>
// }
// `,
// output: $`
// // @keep-dto { "ignores": ["a_b"] }
// a: Partial<{ a: number }>
// b: Required<{ a?: number }>
// c: Readonly<{ a: number }>
// d: NonNullable<{ a: number } | null>
// `,
// errors: ['command-fix'],
// },
// {
// description: 'Utility Types #2: Pick&Omit',
// code: $`
// // @keep-dto
// export interface A {
// a: Pick<{ a: 1 }, 'a'>
// b: Omit<{ a: 1 }, 'a'>
// }
// `,
// output: $`
// // @keep-dto
// export interface A {
// a: Pick<{ a: number }, 'a'>
// b: Omit<{ a: number }, 'a'>
// }
// `,
// errors: ['command-fix'],
// },
// {
// description: 'Utility Types #3: Custom',
// code: $`
// // @keep-dto { "utilities": { Awaited: 0, Promise: 0 } }
// export interface A {
// a: Awaited<Promise<{ a: 1 }>>
// }
// `,
// output: $`
// // @keep-dto { "ignores": ["a_b"] }
// export interface A {
// a: Awaited<Promise<{ a: number }>>
// }
// `,
// errors: ['command-fix'],
// },
{
description: 'Utility Types #1: Partial&Required&Readonly&NonNullable',
code: $`
// @keep-dto
export interface A {
a: Partial<{ a: 1 }>
b: Required<{ a?: 1 }>
c: Readonly<{ a: 1 }>
d: NonNullable<{ a: 1 } | null>
}
`,
output: $`
// @keep-dto
export interface A {
a: Partial<{ a: number }>
b: Required<{ a?: number }>
c: Readonly<{ a: number }>
d: NonNullable<{ a: number } | null>
}
`,
errors: ['command-fix'],
},
{
description: 'Utility Types #2: Pick&Omit',
code: $`
// @keep-dto
export interface A {
a: Pick<{ a: 1 }, 'a'>
b: Omit<{ a: 1 }, 'a'>
}
`,
output: $`
// @keep-dto
export interface A {
a: Pick<{ a: number }, 'a'>
b: Omit<{ a: number }, 'a'>
}
`,
errors: ['command-fix'],
},
{
description: 'Utility Types #3: Custom',
code: $`
type X<A, B, C> = A | B | C
// @keep-dto { "utilities": { "Awaited": 0, "Promise": 0, "X": [0, 2] } }
export interface A {
a: Awaited<Promise<{ a: 1 }>>
b: X<{ a: 1 }, { b: 2 }, { c: 3 }>
}
`,
output: $`
type X<A, B, C> = A | B | C
// @keep-dto { "utilities": { "Awaited": 0, "Promise": 0, "X": [0, 2] } }
export interface A {
a: Awaited<Promise<{ a: number }>>
b: X<{ a: number }, { b: 2 }, { c: number }>
}
`,
errors: ['command-fix'],
},
)
25 changes: 23 additions & 2 deletions src/commands/keep-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export interface KeepDtoInlineOptions {
* @defalut false
*/
literal: false | 'all' | 'union' | 'intersection'
/**
* Custom Utility Types
*/
utilities: Record<string, number | number[]>
}

function normalizeKey(key: string, mode: KeepDtoInlineOptions['key'] = 'camelize') {
Expand All @@ -48,6 +52,12 @@ const reLine = /^[/@:]\s*(?:keep-dto|dto)\s*(\{.*\})?$/
// @regex101 https://regex101.com/?regex=%28%3F%3A%5Cb%7C%5Cs%29%40keep-dto%5Cs*%28%5C%7B.*%5C%7D%29%3F%28%3F%3A%5Cb%7C%5Cs%7C%24%29&flavor=javascript
const reBlock = /(?:\b|\s)@keep-dto\s*(\{.*\})?(?:\b|\s|$)/

const typeReferences = {
$1_0: ['Array', 'Partial', 'Required', 'Readonly', 'NonNullable'],
$2_0: ['Pick', 'Omit'],
$2_1: ['Record'],
}

export const keepDto = defineCommand({
name: 'keep-dto',
commentType: 'both',
Expand Down Expand Up @@ -149,12 +159,23 @@ export const keepDto = defineCommand({
else if (typeNode.type === AST_NODE_TYPES.TSTypeReference) {
const params = typeNode.typeArguments?.params
if (typeNode.typeName.type === AST_NODE_TYPES.Identifier) {
if (typeNode.typeName.name === 'Array' && params?.length === 1) {
if (typeReferences.$1_0.includes(typeNode.typeName.name) && params?.length === 1) {
formatTypeNode(params[0], prefix)
}
else if (typeNode.typeName.name === 'Record' && params?.length === 2) {
else if (typeReferences.$2_0.includes(typeNode.typeName.name) && params?.length === 2) {
formatTypeNode(params[0], prefix)
}
else if (typeReferences.$2_1.includes(typeNode.typeName.name) && params?.length === 2) {
formatTypeNode(params[1], prefix)
}
else {
const opt = options?.utilities?.[typeNode.typeName.name] ?? []
const indexes = Array.isArray(opt) ? opt : [opt]
const max = Math.max(...indexes)
if (params && params.length > max) {
indexes.forEach(index => formatTypeNode(params[index], prefix))
}
}
}
}
}
Expand Down

0 comments on commit 53fc110

Please sign in to comment.