Skip to content

Commit a8ce450

Browse files
authored
refactor(types): migrate from tsd to tstyche (#93)
1 parent 24a2547 commit a8ce450

3 files changed

Lines changed: 142 additions & 149 deletions

File tree

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"lint:fix": "eslint --fix",
1111
"test": "npm run test:unit && npm run test:typescript",
1212
"test:unit": "c8 tape test/*.js",
13-
"test:typescript": "tsd"
13+
"test:typescript": "tstyche"
1414
},
1515
"repository": {
1616
"type": "git",
@@ -56,7 +56,7 @@
5656
"neostandard": "^0.13.0",
5757
"tape": "^5.7.5",
5858
"c8": "^11.0.0",
59-
"tsd": "^0.33.0"
59+
"tstyche": "^7.0.0"
6060
},
6161
"files": [
6262
"LICENSE",
@@ -71,4 +71,4 @@
7171
"object",
7272
"immutable"
7373
]
74-
}
74+
}

types/index.test-d.ts

Lines changed: 0 additions & 146 deletions
This file was deleted.

types/index.tst.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { expect } from 'tstyche'
2+
import { deepmerge, type DeepMergeFn, type DeepMergeAllFn, DeepMergeDefinedFn, DeepMergeAllDefinedFn } from '.'
3+
4+
expect(deepmerge()).type.toBeAssignableTo<Function>()
5+
expect(deepmerge()).type.toBe<DeepMergeFn>()
6+
7+
expect(deepmerge()({ a: 'a' }, { b: 'b' }).a).type.toBe<string>()
8+
expect(deepmerge()({ a: 'a' }, { b: 'b' }).b).type.toBe<string>()
9+
expect(deepmerge()({ a: 2 }, { b: 'b' }).a).type.toBe<number>()
10+
expect(deepmerge()({ a: 2 }, { b: 'b' }).b).type.toBe<string>()
11+
expect(deepmerge()({ a: 2 }, { a: 'b' }).a).type.toBe<string>()
12+
13+
expect(deepmerge).type.not.toBeCallableWith(1)
14+
expect(deepmerge).type.not.toBeCallableWith({ symbols: 2 })
15+
expect(deepmerge).type.not.toBeCallableWith({ symbol: 2 })
16+
17+
expect(deepmerge({ symbols: true })).type.toBeAssignableTo<Function>()
18+
expect(deepmerge({ symbols: true })).type.toBe<DeepMergeFn>()
19+
20+
expect(deepmerge()('string', { a: 'string' }).a).type.toBe<string>()
21+
expect(deepmerge()(1, { a: 'string' }).a).type.toBe<string>()
22+
23+
expect(deepmerge()<Object, string>({ a: 'string' }, 'string')).type.toBe<string>()
24+
expect(deepmerge()<Object, number>({ a: 'string' }, 1)).type.toBe<number>()
25+
expect(deepmerge()({ a: 'string' }, new Date())).type.toBe<Date>()
26+
expect(deepmerge()({ a: 'string' }, /a/g)).type.toBe<RegExp>()
27+
expect(deepmerge()(/a/, {})).type.toBe<{}>()
28+
29+
expect(deepmerge()({ a: 'string' }, { a: 1 }).a).type.toBe<number>()
30+
expect(deepmerge()({ a: 'string' }, { b: 1 }).a).type.toBe<string>()
31+
expect(deepmerge()({ a: 'string' }, { }).a).type.toBe<string>()
32+
expect(deepmerge()({ a: 'string' }, { b: 1 }).b).type.toBe<number>()
33+
expect(deepmerge()({ a: { a: 'string' } }, { b: 1 }).a).type.toBe<{ a: string }>()
34+
expect(deepmerge()({ a: { a: 'string' } }, { a: { a: 1 } }).a).type.toBe<{ a: number }>()
35+
expect(deepmerge()({ a: { a: 'string' } }, { a: { a: 1, b: 'string' } }).a).type.toBe<{ a: number, b: string }>()
36+
expect(deepmerge()({ a: { a: { a: 'string' } } }, { a: { a: 1, b: 'string' } }).a).type.toBe<{ a: number, b: string }>()
37+
expect(deepmerge()({ a: { a: { a: 'string' } } }, { a: { a: { b: 'string' } } }).a).type.toBe<{ a: { a: string, b: string } }>()
38+
expect(deepmerge()({ a: [1, 2, 3, 4] }, { a: 'string' }).a).type.toBe<string>()
39+
expect(deepmerge()({ a: [1, 2, 3, 4] }, { a: [1, 2, 3, 4] }).a).type.toBe<number[]>()
40+
expect(deepmerge()({ a: [1, 2, 3, 4] }, { a: ['a'] }).a).type.toBe<(number | string)[]>()
41+
expect(deepmerge()({ a: [1, 2, 3, 4] as readonly number[] }, { a: ['a'] }).a).type.toBe<(number | string)[]>()
42+
expect(deepmerge()({ a: [1, 2, 3, 4] as const }, { a: ['a'] as const }).a).type.toBe<[1, 2, 3, 4, 'a']>()
43+
expect(deepmerge()({ a: [1] }, { a: [2] }).a).type.toBe<Array<number>>()
44+
expect(deepmerge()({ a: { b: {} } }, { a: { b: [2] } }).a).type.toBe<{ b: number[] }>()
45+
expect(deepmerge()({ a: { b: {} } }, { a: { b: new Date() } }).a).type.toBe<{ b: Date }>()
46+
expect(deepmerge()({ a: { b: {} } }, { a: { b: /abc/g } }).a).type.toBe<{ b: RegExp }>()
47+
expect(deepmerge()({ a: { b: {} } }, new Date())).type.toBe<Date>()
48+
expect(deepmerge()({ a: { b: {} } }, new Map())).type.toBe<Map<any, any>>()
49+
50+
expect(deepmerge({ all: true })).type.toBeAssignableTo<Function>()
51+
expect(deepmerge({ all: true })).type.toBe<DeepMergeAllFn>()
52+
expect(deepmerge({ all: true, symbols: true })).type.toBeAssignableTo<Function>()
53+
expect(deepmerge({ all: true, symbols: true })).type.toBe<DeepMergeAllFn>()
54+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }).a).type.toBe<string>()
55+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }, { b: 'a' }).a).type.toBe<string>()
56+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }, { b: 'a' }).b).type.toBe<string>()
57+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }, { a: 2 }).a).type.toBe<number>()
58+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }, 2)).type.toBe<number>()
59+
expect(deepmerge({ all: true, symbols: true })({ a: 'a' }, 'string')).type.toBe<string>()
60+
61+
expect(deepmerge).type.not.toBeCallableWith({ mergeArray: function () {} })
62+
expect(deepmerge).type.not.toBeCallableWith({
63+
mergeArray: function () {
64+
return () => 'test'
65+
}
66+
})
67+
68+
deepmerge({
69+
mergeArray: function (options) {
70+
expect(options.clone).type.toBe<(value: any) => any>()
71+
const clone = options.clone
72+
return function (target, source) {
73+
return clone(target.concat(source))
74+
}
75+
}
76+
})
77+
deepmerge({
78+
mergeArray: function () {
79+
return function (_target, source) {
80+
return source
81+
}
82+
}
83+
})
84+
deepmerge({
85+
isMergeableObject: function (value) {
86+
return true
87+
}
88+
})
89+
90+
expect(deepmerge.isMergeableObject).type.toBe<(value: any) => boolean>()
91+
92+
expect(deepmerge({ onlyDefinedProperties: true })).type.toBe<DeepMergeDefinedFn>()
93+
expect(deepmerge({ all: true, onlyDefinedProperties: true })).type.toBe<DeepMergeAllDefinedFn>()
94+
95+
interface FullOptions {
96+
apiUrl: string
97+
timeout: number
98+
nested: {
99+
enabled: boolean
100+
value: string
101+
}
102+
}
103+
104+
type PartialOptions = Partial<FullOptions>
105+
106+
const fullTarget: FullOptions = { apiUrl: 'url', timeout: 100, nested: { enabled: true, value: 'test' } }
107+
const partialSource: PartialOptions = { timeout: 200 }
108+
109+
const mergedDefined = deepmerge({ onlyDefinedProperties: true })(fullTarget, partialSource)
110+
expect(mergedDefined.apiUrl).type.toBe<string>()
111+
expect(mergedDefined.timeout).type.toBe<number>()
112+
expect(mergedDefined.nested).type.toBe<{ enabled: boolean; value: string }>()
113+
114+
expect(mergedDefined).type.toBeAssignableTo<FullOptions>()
115+
116+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
117+
const mergedRegular = deepmerge()(fullTarget, partialSource)
118+
119+
type DeepPartialOptions = {
120+
apiUrl?: string
121+
timeout?: number
122+
nested?: {
123+
enabled?: boolean
124+
value?: string
125+
}
126+
}
127+
128+
const deepPartialSource: DeepPartialOptions = { nested: { enabled: false } }
129+
const mergedDeep = deepmerge({ onlyDefinedProperties: true })(fullTarget, deepPartialSource)
130+
expect(mergedDeep.apiUrl).type.toBe<string>()
131+
expect(mergedDeep.timeout).type.toBe<number>()
132+
expect(mergedDeep.nested).type.toBeAssignableTo<{ enabled: boolean; value: string }>()
133+
134+
const mergedAll = deepmerge({ all: true, onlyDefinedProperties: true })(
135+
fullTarget,
136+
{ timeout: 300 } as PartialOptions,
137+
{ apiUrl: 'newUrl' } as PartialOptions
138+
)
139+
expect(mergedAll).type.toBeAssignableTo<FullOptions>()

0 commit comments

Comments
 (0)