Reputation: 83
I would like to declare few simple types, to distinguish strings like "url", "absolute url", "json", etc. It would be enough, to show declared type in hint, but type checking would be even better (i.e. "url" couldn't be passed to function expecting "absolute url").
The issue is that TypeScript/VSC understands, that "url" is a string and skips my declared type. Is there any way, to show declared type in hint? I don't mind hacky solutions as long as they don't break TypeScript features.
Sample code - I want to see "const data: url" in hint:
What I want to see (but this solution is bad, because url shouldn't be a number):
Upvotes: 0
Views: 3189
Reputation: 25820
Solution
Intersect your primitive type with an empty object type.
type url = string & {};
Explanation
Note that {}
does not mean empty object as you may think. It represents everything but null | undefined
. Here, mixing string
with {}
doesn't change anything, but the name will now be preserved.
Upvotes: 3
Reputation: 1465
There is no guarantee that your type aliases get preserved as typescript does not care if something is a string
or a url
as they have the same underlying type. This is due to the structural (as opposed to nominal) typing philosophy typescript adopts, although there are some proposals to support this use case (https://github.com/microsoft/TypeScript/pull/33038, https://github.com/microsoft/TypeScript/pull/33290).
Your best bet in the mean time is to use a function with a return type like so:
As for your other question - different url types - you can achieve something like this using discriminated unions & adding properties to the string
object:
type url = string & { _subtype: 'absoluteUrl' | 'relativeUrl' | 'other' }
type absoluteUrl = url & { _subtype: 'absoluteUrl' }
type relativeUrl = url & { _subtype: 'relativeUrl' }
const createAbsoluteUrl = (input: string) => {
const createdAbsoluteUrl = input
;(createdAbsoluteUrl as any)._subtype = 'absoluteUrl'
return createdAbsoluteUrl as absoluteUrl
}
const createRelativeUrl = (input: string) => {
const createdRelativeUrl = input
;(createdRelativeUrl as any)._subtype = 'relativeUrl'
return createdRelativeUrl as relativeUrl
}
const expectAbsoluteUrl = (input: absoluteUrl) => {
// something
}
const expectRelativeUrl = (input: relativeUrl) => {
// something
}
You should then see type errors as you expect:
You may also find user defined type guards useful if you go with this approach
Upvotes: 2
Reputation: 602
I didn't find a hack to achieve something you've asked for using primitive types.
But don't you mind using enum
?
As a pros you will have your Url's in one place.
Upvotes: 1