Closed achingbrain closed 3 years ago
we aren't using types for data validation any more (please let's not do this)
I'm not sure I understand what you mean here.
we can pass
cid.version
in to other functions without needing to do weird type contortions to account for it only being0|1
Just a side note 0|1
is subtype of number so it will be valid number
and should not be a problem. It does not work other way round though.
c) we can handle CIDv2 if/when that comes along
When we add support for CIDv2 it would be great time to change type to 0|1|2
. In fact the main reason to use types like 0|1
is to help with those kind of things.
I'm not sure I understand what you mean here.
What I mean is, 0
, 1
, 2
are values and we're using the type to constrain the value, sort of like an enum, except this is a version number which doesn't seem like the sort of thing you'd use an enum for.
Is there an existing code pattern that the constraint to 0|1
is causing problems for? I can imagine one, but I can't imagine a realistic one where a CID version number is coming from an unconstrained number
that might have some other use. Or are we just wanting to give API consumers more flexibility so that, in the eventuality of a 2
, it doesn't get extra-hard?
Is there an existing code pattern that the constraint to
0|1
is causing problems for?
Yes, because .version
is less restrictive type you cannot use it as the first argument to the CID constructor:
const cid1 = new CID('Qmfoo')
const cid2 = new CID(cid1.version, cid1.codec, /* ..etc */) // not allowed
Though it looks like #130 has approached this by going the other way and making it more restrictive.
Anyway my point is, a version number is not a type - it cannot be subclassed for polymorphism, nor does it define or possess an interface that can be used for abstraction. It's just a number, which is a type.
That we only support 0
and 1
as values for the version number is a coincidence and enforcing that with a type system seems wrong.
Anyway my point is, a version number is not a type - it cannot be subclassed for polymorphism, nor does it define or possess an interface that can be used for abstraction. It's just a number, which is a type.
In algebric data types that is not exactly true and typescript type system does qualify as algebraic, where you can think of number a union of all possible numbers. And in algebric data types you can refine types by narrowing them down (e.g. with switch or if statements in TS). You can even subtype (e.g number & string would be a supertype, it can’t be instantiated but sometimes that is useful in fact that is more or less what never
type is).
That we only support
0
and1
as values for the version number is a coincidence and enforcing that with a type system seems wrong.
I would suggest following view instead
0
or 1
.In more practical terms program that wishes not to fail should either enclose call to CID(verison, ...
in try { }
or ensure that version is 0
or 1
before passing. Encoding version as 0|1
makes that explicit.
Closing since we decided to go with alternative proposal & revisit if it will end up to be a pain.
We use the TS typing to enforce only
0
or1
as version numbers, but mark theversion
property of a CID asnumber
which means it can be any value.Here we relax the version number input to be the same as the
version
property which means:a) we aren't using types for data validation any more (please let's not do this) b) we can pass
cid.version
in to other functions without needing to do weird type contortions to account for it only being0|1
c) we can handle CIDv2 if/when that comes along