Skip to content

Commit 2cb1d16

Browse files
authored
fix: improve types of generated index.d.ts (#481)
1 parent 97d97bd commit 2cb1d16

File tree

5 files changed

+129
-32
lines changed

5 files changed

+129
-32
lines changed

src/collection.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { test, expect, expectTypeOf } from 'vitest'
2+
import { Collection, type UniqueWithLocations } from './collection'
3+
4+
let loc = { start: { line: 1, column: 1, offset: 1 }, end: { offset: 2 } }
5+
6+
test('basic collection - size()', () => {
7+
let collection = new Collection()
8+
collection.p('a', loc)
9+
collection.p('a', loc)
10+
expect(collection.size()).toEqual(2)
11+
})
12+
13+
test('count with useLocations=undefined', () => {
14+
let collection = new Collection()
15+
collection.p('a', loc)
16+
collection.p('a', loc)
17+
18+
let count = collection.c()
19+
expect(count).toEqual({
20+
total: 2,
21+
totalUnique: 1,
22+
unique: {
23+
a: 2,
24+
},
25+
uniquenessRatio: 0.5,
26+
})
27+
expectTypeOf(count['uniqueWithLocations']).toBeUndefined()
28+
})
29+
30+
test('count with useLocations=false', () => {
31+
let collection = new Collection(false)
32+
collection.p('a', loc)
33+
collection.p('a', loc)
34+
35+
let count = collection.c()
36+
expect(count).toEqual({
37+
total: 2,
38+
totalUnique: 1,
39+
unique: {
40+
a: 2,
41+
},
42+
uniquenessRatio: 0.5,
43+
})
44+
expectTypeOf(count['uniqueWithLocations']).toBeUndefined()
45+
})
46+
47+
test('count with useLocations=true', () => {
48+
let collection = new Collection(true)
49+
collection.p('a', loc)
50+
collection.p('a', loc)
51+
52+
let pos = { offset: 1, length: 1, line: 1, column: 1 }
53+
let count = collection.c()
54+
expect(count).toEqual({
55+
total: 2,
56+
totalUnique: 1,
57+
unique: {},
58+
uniquenessRatio: 0.5,
59+
uniqueWithLocations: { a: [pos, pos] },
60+
})
61+
expectTypeOf(count['uniqueWithLocations']).toMatchObjectType<UniqueWithLocations>()
62+
})

src/collection.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1-
import type { CssLocation } from 'css-tree'
1+
export type Location = {
2+
line: number
3+
column: number
4+
offset: number
5+
length: number
6+
}
7+
8+
export type UniqueWithLocations = Record<string, Location[]>
9+
10+
export type CollectionCount<WithLocations extends boolean = false> = {
11+
total: number
12+
totalUnique: number
13+
unique: Record<string, number>
14+
uniquenessRatio: number
15+
} & (WithLocations extends true ? { uniqueWithLocations: UniqueWithLocations } : { uniqueWithLocations?: undefined })
216

3-
export class Collection {
17+
export class Collection<UseLocations extends boolean = false> {
418
#items: Map<string | number, number[]>
519
#total: number
620
#nodes: number[] = []
7-
#useLocations: boolean
21+
#useLocations: UseLocations
822

9-
constructor(useLocations = false) {
23+
constructor(useLocations: UseLocations = false as UseLocations) {
1024
this.#items = new Map()
1125
this.#total = 0
1226

@@ -46,8 +60,8 @@ export class Collection {
4660
return this.#total
4761
}
4862

49-
c() {
50-
let uniqueWithLocations: Map<string | number, { line: number; column: number; offset: number; length: number }[]> = new Map()
63+
c(): CollectionCount<UseLocations> {
64+
let uniqueWithLocations: Map<string | number, Location[]> = new Map()
5165
let unique: Record<string, number> = {}
5266
let useLocations = this.#useLocations
5367
let items = this.#items
@@ -72,14 +86,23 @@ export class Collection {
7286
})
7387

7488
let total = this.#total
75-
let data = {
89+
90+
if (useLocations) {
91+
return {
92+
total,
93+
totalUnique: size,
94+
unique,
95+
uniquenessRatio: total === 0 ? 0 : size / total,
96+
uniqueWithLocations: Object.fromEntries(uniqueWithLocations),
97+
} as unknown as CollectionCount<UseLocations>
98+
}
99+
100+
return {
76101
total,
77102
totalUnique: size,
78103
unique,
79104
uniquenessRatio: total === 0 ? 0 : size / total,
80-
uniqueWithLocations: useLocations ? Object.fromEntries(uniqueWithLocations) : undefined,
81-
}
82-
83-
return data
105+
uniqueWithLocations: undefined,
106+
} as unknown as CollectionCount<UseLocations>
84107
}
85108
}

src/context-collection.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import type { CssLocation } from 'css-tree'
2-
import { Collection } from './collection.js'
2+
import { Collection, type CollectionCount } from './collection.js'
33

4-
export class ContextCollection {
5-
#list: Collection
6-
#contexts: Map<string, Collection>
7-
#useLocations: boolean
4+
export class ContextCollection<UseLocations extends boolean = false> {
5+
#list: Collection<UseLocations>
6+
#contexts: Map<string, Collection<UseLocations>>
7+
#useLocations: UseLocations
88

9-
constructor(useLocations: boolean) {
9+
constructor(useLocations: UseLocations) {
1010
this.#list = new Collection(useLocations)
1111
this.#contexts = new Map()
1212
this.#useLocations = useLocations
@@ -29,7 +29,7 @@ export class ContextCollection {
2929
}
3030

3131
count() {
32-
let itemsPerContext = new Map()
32+
let itemsPerContext: Map<string, CollectionCount<UseLocations>> = new Map()
3333

3434
for (let [context, value] of this.#contexts.entries()) {
3535
itemsPerContext.set(context, value.c())

src/index.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,22 @@ function ratio(part: number, total: number): number {
4343
return part / total
4444
}
4545

46-
let defaults = {
47-
useLocations: false,
48-
}
49-
50-
type Options = {
46+
export type Options = {
5147
/** @description Use Locations (`{ 'item': [{ line, column, offset, length }] }`) instead of a regular count per occurrence (`{ 'item': 3 }`) */
5248
useLocations?: boolean
5349
}
5450

55-
export function analyze(css: string, options: Options = {}) {
56-
let settings = Object.assign({}, defaults, options)
57-
let useLocations = settings.useLocations === true
51+
export function analyze(css: string, options?: Options & { useLocations?: false | undefined }): ReturnType<typeof analyzeInternal<false>>
52+
export function analyze(css: string, options: Options & { useLocations: true }): ReturnType<typeof analyzeInternal<true>>
53+
export function analyze(css: string, options: Options = {}): any {
54+
const useLocations = options.useLocations === true
55+
if (useLocations) {
56+
return analyzeInternal(css, options, true)
57+
}
58+
return analyzeInternal(css, options, false)
59+
}
60+
61+
function analyzeInternal<T extends boolean>(css: string, options: Options, useLocations: T) {
5862
let start = Date.now()
5963

6064
/**
@@ -77,8 +81,14 @@ export function analyze(css: string, options: Options = {}) {
7781
let embedSize = 0
7882
let embedTypes = {
7983
total: 0,
80-
/** @type {Map<string, { size: number, count: number } & ({ uniqueWithLocations?: undefined } | ({ uniqueWithLocations: { offset: number, line: number, column: number, length: number }[] })) }>} */
81-
unique: new Map(),
84+
unique: new Map() as Map<
85+
string,
86+
{
87+
size: number
88+
count: number
89+
uniqueWithLocations?: { offset: number; line: number; column: number; length: number }[]
90+
}
91+
>,
8292
}
8393

8494
let startParse = Date.now()
@@ -430,11 +440,11 @@ export function analyze(css: string, options: Options = {}) {
430440
}
431441

432442
if (embedTypes.unique.has(type)) {
433-
let item = embedTypes.unique.get(type)
443+
let item = embedTypes.unique.get(type)!
434444
item.count++
435445
item.size += size
436446
embedTypes.unique.set(type, item)
437-
if (useLocations) {
447+
if (useLocations && item.uniqueWithLocations) {
438448
item.uniqueWithLocations.push(loc)
439449
}
440450
} else {

vite.config.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { codecovVitePlugin } from '@codecov/vite-plugin'
66
export default defineConfig({
77
build: {
88
lib: {
9-
entry: resolve(__dirname, 'src/index.js'),
9+
entry: resolve(__dirname, 'src/index.ts'),
1010
formats: ['es'],
1111
},
1212
rollupOptions: {
@@ -16,7 +16,9 @@ export default defineConfig({
1616
},
1717
},
1818
plugins: [
19-
dts(),
19+
dts({
20+
rollupTypes: true,
21+
}),
2022
codecovVitePlugin({
2123
enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
2224
bundleName: 'analyzeCss',

0 commit comments

Comments
 (0)