Skip to content

Commit a5fbf61

Browse files
authored
feat: add hasCode to Digest (#308)
To give a hint to tsc that a `MultihashDigest` has a specific code, add a disambiguator `hasCode` function. This lets us define functions that require a certain multihash code with type saftey.
1 parent c55bdfd commit a5fbf61

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/hashes/digest.ts

+7
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,10 @@ export class Digest<Code extends number, Size extends number> implements Multiha
6969
this.bytes = bytes
7070
}
7171
}
72+
73+
/**
74+
* Used to check that the passed multihash has the passed code
75+
*/
76+
export function hasCode <T extends number> (digest: MultihashDigest, code: T): digest is MultihashDigest<T> {
77+
return digest.code === code
78+
}

src/hashes/identity.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { coerce } from '../bytes.js'
22
import * as Digest from './digest.js'
33

4-
const code = 0x0
4+
const code: 0x0 = 0x0
55
const name = 'identity'
66

77
const encode: (input: Uint8Array) => Uint8Array = coerce

test/test-multihash.spec.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { hash as slSha512 } from '@stablelib/sha512'
55
import { assert } from 'aegir/chai'
66
import { sha1 as chSha1 } from 'crypto-hash'
77
import { fromHex, fromString } from '../src/bytes.js'
8-
import { decode as decodeDigest, create as createDigest } from '../src/hashes/digest.js'
8+
import { decode as decodeDigest, create as createDigest, hasCode as digestHasCode } from '../src/hashes/digest.js'
99
import { identity } from '../src/hashes/identity.js'
1010
import { sha1 } from '../src/hashes/sha1.js'
1111
import { sha256, sha512 } from '../src/hashes/sha2.js'
1212
import invalid from './fixtures/invalid-multihash.js'
1313
import valid from './fixtures/valid-multihash.js'
14+
import type { MultihashDigest } from '../src/cid.js'
1415

1516
const sample = (code: number | string, size: number, hex: string): Uint8Array => {
1617
const toHex = (i: number | string): string => {
@@ -158,4 +159,28 @@ describe('multihash', () => {
158159
assert.match(String(error), /Unknown type, must be binary type/)
159160
}
160161
})
162+
163+
describe('hasCode', () => {
164+
it('asserts that a multihash has the expected code', () => {
165+
const buf = Uint8Array.from([0, 1, 2, 3])
166+
167+
// remove code type from MultihashDigest
168+
const hash = decodeDigest(identity.digest(buf).bytes)
169+
170+
// a function that requires a specific type of multihash
171+
function needIdentity (_: MultihashDigest<0x0>): void {
172+
173+
}
174+
175+
assert.isTrue(digestHasCode(hash, identity.code))
176+
177+
// @ts-expect-error fails to compile as hash is MultihashDigest<number>
178+
needIdentity(hash)
179+
180+
// hint to tsc that hash is MultihashDigest<0x0>
181+
if (digestHasCode(hash, identity.code)) {
182+
needIdentity(hash)
183+
}
184+
})
185+
})
161186
})

0 commit comments

Comments
 (0)