How do I let the following code know that u
is a string?
I am currently getting
Argument of type 'string | number | symbol' is not assignable to parameter of type 'string'
interface MyDef {
a: "a",
}
export class Router<t>{
public generate<u extends keyof t>(path: u) {
this.test(path)
}
public test(s: string) {
console.log(s);
}
}
const x = new Router<MyDef>();
// "a" is defined in MyDef - should work
x.generate("a");
// should not compile
x.generate("not-in-mydef");
Things I have tried
interface RouteSet {
[k: string]: string;
}
// …
export class Router<t extends RouteSet>{
export class Router<t extends Record<string,string>>{
export class Router<t extends {[key: string]: string}>{
I can't seem to find a way to let TypeScript know I only ever want u
to be a string.
I can this.test(path as any as string)
to quiet the compiler, but that's far from ideal.
CodePudding user response:
If you intersect keyof t
with string
, you'll get only the keys of t
that are strings:
class Router<t> {
public generate<u extends keyof t & string>(path: u) {
this.test(path)
}
public test(s: string) {
console.log(s);
}
}
See some examples in the playground below:
CodePudding user response:
Keys of a type can be strings, numbers or symbols. You have 2 options:
Option 1: Take any key on test
function
class Router<T>{
public generate(path: keyof T) {
this.test(path)
}
public test(s: keyof T) {
console.log(s);
}
}
Option 2: restrict allowed keys to strings
class Router1<T>{
public generate(path: keyof T & string) {
this.test(path)
}
public test(s: string) {
console.log(s);
}
}
Note: the generic type is not necessary - I removed it.