With a concept:
type Stringable = concept s
`$`(s) is string
proc doThing(s: Stringable) = echo s
doThing(100)
doThing("hello")
type NewType = distinct int
assert not compiles(doThing(NewType(100)))
recommend surfacing concepts in the docs
I checked the
but didnt find it until i checked the index
Concept are a good solution. You can also use when compiles with generic or templates :
type
Stringable = object
NonStringable = object
proc `$`(s: NonStringable) {.error: "NonStringable type is non stringable".}
proc `$`(s: Stringable) : string =
"123"
template testMe(s: typed) : string =
when compiles($(s)):
$s
else:
{.error: "Non stringable type passed".}
proc testMe2[T](s: T) : string =
when compiles($(s)):
$s
else:
{.error: "Non stringable type passed".}
var s : Stringable
var ns : NonStringable
echo testMe(s) # OK
echo testMe2(s) # OK
# echo testMe(ns) # do not compile
# echo testMe2(ns) # do not compile
Another option, if you don't want to mess around with concepts, is to simply do something like this:
proc doThing(x: string) = echo x
template doThing(x: untyped): untyped = doThing($x)
What this does is basically say that doThing only accepts a string, but create an overload with a template which tries to call $ on the input. Since the string version of doThing is more specific that will be chosen if you already have a string, and the template version will be called if it's not a string.