打字稿方法查询字符串到对象
Typescript method querystring to object
我正在制作一种将查询字符串转换为对象的方法。方法很好用,就是打字报错
https://jsfiddle.net/h723zuen/2/
const fromQueryString = <
T extends {
[x: string]: string | number | boolean | string[] | number[] | boolean[];
}
>(
querystring: string,
) => {
const out: {
[x: string]: string | number | boolean | string[] | number[] | boolean[];
} = {};
const arr = querystring.split('&');
arr.forEach((a) => {
const [key, value] = a.split('=');
console.log(key, toValue(value), out, key in out);
if (!!key && !!value) {
if (key in out) {
out[key] = Array.isArray(out[key])
? out[key].push(toValue(value))
: [out[key], toValue(value)];
} else {
out[key] = toValue(value);
}
console.log(out);
}
});
return out as T;
};
function toValue(mix: string) {
const str = decodeURIComponent(mix);
if (str === 'false') return false;
if (str === 'true') return true;
return +str * 0 === 0 ? +str : str;
}
根据我的理解,Typescript 仍然包含一些有时很难理解的故障。
例如,这与您的案例非常相关:
// (1)
// doesn't work since Typescript can't infer (string | number) as element
type Foo = string[] | number[];
const foo: Foo = [];
foo.push(1); // you would see error here as we push a number element
// (2)
// Works as expected
type Baz = Array<string | number>;
const baz: Baz = [];
baz.push(1);
回到你的案例,我建议你将你的类型转换为案例 (2)。这是您转换后的代码:
// simplify things by group things again
type BaseType = string | number | boolean;
type BaseObj = Record<string, BaseType | BaseType[]>;
const fromQueryString = <T extends BaseObj>(
querystring: string,
) => {
const out: BaseObj = {};
const arr = querystring.split('&');
arr.forEach((a) => {
const [key, value] = a.split('=');
console.log(key, toValue(value), out, key in out);
if (!!key && !!value) {
if (key in out) {
const v = out[key];
out[key] = Array.isArray(v)
? v.push(toValue(value))
: [v, toValue(value)];
} else {
out[key] = toValue(value);
}
console.log(out);
}
});
return out as T;
};
function toValue(mix: string) {
const str = decodeURIComponent(mix);
if (str === 'false') return false;
if (str === 'true') return true;
return +str * 0 === 0 ? +str : str;
}
我正在制作一种将查询字符串转换为对象的方法。方法很好用,就是打字报错
https://jsfiddle.net/h723zuen/2/
const fromQueryString = <
T extends {
[x: string]: string | number | boolean | string[] | number[] | boolean[];
}
>(
querystring: string,
) => {
const out: {
[x: string]: string | number | boolean | string[] | number[] | boolean[];
} = {};
const arr = querystring.split('&');
arr.forEach((a) => {
const [key, value] = a.split('=');
console.log(key, toValue(value), out, key in out);
if (!!key && !!value) {
if (key in out) {
out[key] = Array.isArray(out[key])
? out[key].push(toValue(value))
: [out[key], toValue(value)];
} else {
out[key] = toValue(value);
}
console.log(out);
}
});
return out as T;
};
function toValue(mix: string) {
const str = decodeURIComponent(mix);
if (str === 'false') return false;
if (str === 'true') return true;
return +str * 0 === 0 ? +str : str;
}
根据我的理解,Typescript 仍然包含一些有时很难理解的故障。
例如,这与您的案例非常相关:
// (1)
// doesn't work since Typescript can't infer (string | number) as element
type Foo = string[] | number[];
const foo: Foo = [];
foo.push(1); // you would see error here as we push a number element
// (2)
// Works as expected
type Baz = Array<string | number>;
const baz: Baz = [];
baz.push(1);
回到你的案例,我建议你将你的类型转换为案例 (2)。这是您转换后的代码:
// simplify things by group things again
type BaseType = string | number | boolean;
type BaseObj = Record<string, BaseType | BaseType[]>;
const fromQueryString = <T extends BaseObj>(
querystring: string,
) => {
const out: BaseObj = {};
const arr = querystring.split('&');
arr.forEach((a) => {
const [key, value] = a.split('=');
console.log(key, toValue(value), out, key in out);
if (!!key && !!value) {
if (key in out) {
const v = out[key];
out[key] = Array.isArray(v)
? v.push(toValue(value))
: [v, toValue(value)];
} else {
out[key] = toValue(value);
}
console.log(out);
}
});
return out as T;
};
function toValue(mix: string) {
const str = decodeURIComponent(mix);
if (str === 'false') return false;
if (str === 'true') return true;
return +str * 0 === 0 ? +str : str;
}