使用可选参数的键进行索引
Indexing with keys of optional parameters
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options : IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
Object.keys(options).forEach(function(key) {
html = html.replace('{{' + key + '}}', options[key]);//<==== Error
});
return html;
}
访问选项[key]抛出如下错误
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IHtmlProperties'.
No index signature with a parameter of type 'string' was found on type 'IHtmlProperties'.
如果 IHtmlProperties 没有可选参数,我可以轻松编写 options[key as keyof IHtmlProperties]。
不过这里的IHtmlProperties有一些可选参数。知道如何解决这个问题吗?
更新修复
较早的问题是因为 replace 具有未定义的值。因此检查值有效性修复了错误
let html = htmlTemplate;
(Object.keys(options)).forEach(function(key) {
const value = options[key as keyof IHtmlProperties];
if(value) {
html = html.replace('{{' + key + '}}', value);
}
});
return html;
接受的答案帮助我弄明白了!谢谢!
请看回答,与使用Object.keys
相关。
因此,您已经知道 Object.keys
returns 字符串数组。这意味着 forEach(function(key)
中的 key
与 options
的类型无关。换句话说,您只能使用 website
和 favIcon
作为 options
的索引,而 key
的类型要宽得多,它是 string
.
类型string
是"website" | "favIcon"
(keyof IHtmlProperties
)的超类型,因此不允许使用。想象一下,您可以使用任何字符串作为 key
: options["any string"]
。此表达式 returns undefined
因为 "any string"
不能用于索引 options
对象。
让我们定义我们的函数:
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options: IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
return (Object.keys(options) as Array<keyof IHtmlProperties>).reduce((acc, key) => {
const value = options[key];
return value ? acc.replace('{{' + key + '}}', value) : acc
}, html);
}
Playground
您可能已经注意到,key
具有正确的类型。由于 replace
的第二个参数的预期类型是 string
我们不允许传递 undefined
.
常量 value
具有 string | undefined
类型,这就是为什么它不允许作为参数。我们需要确保它是一个 string
,这就是我添加三元运算符的原因。
版本forEach
:
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options: IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
(Object.keys(options) as Array<keyof IHtmlProperties>)
.forEach((key) => {
const value = options[key];
if (value) {
html.replace(`{{${key}}}`, value)
}
});
return html;
}
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options : IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
Object.keys(options).forEach(function(key) {
html = html.replace('{{' + key + '}}', options[key]);//<==== Error
});
return html;
}
访问选项[key]抛出如下错误
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IHtmlProperties'.
No index signature with a parameter of type 'string' was found on type 'IHtmlProperties'.
如果 IHtmlProperties 没有可选参数,我可以轻松编写 options[key as keyof IHtmlProperties]。
不过这里的IHtmlProperties有一些可选参数。知道如何解决这个问题吗?
更新修复 较早的问题是因为 replace 具有未定义的值。因此检查值有效性修复了错误
let html = htmlTemplate;
(Object.keys(options)).forEach(function(key) {
const value = options[key as keyof IHtmlProperties];
if(value) {
html = html.replace('{{' + key + '}}', value);
}
});
return html;
接受的答案帮助我弄明白了!谢谢!
请看Object.keys
相关。
因此,您已经知道 Object.keys
returns 字符串数组。这意味着 forEach(function(key)
中的 key
与 options
的类型无关。换句话说,您只能使用 website
和 favIcon
作为 options
的索引,而 key
的类型要宽得多,它是 string
.
类型string
是"website" | "favIcon"
(keyof IHtmlProperties
)的超类型,因此不允许使用。想象一下,您可以使用任何字符串作为 key
: options["any string"]
。此表达式 returns undefined
因为 "any string"
不能用于索引 options
对象。
让我们定义我们的函数:
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options: IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
return (Object.keys(options) as Array<keyof IHtmlProperties>).reduce((acc, key) => {
const value = options[key];
return value ? acc.replace('{{' + key + '}}', value) : acc
}, html);
}
Playground
您可能已经注意到,key
具有正确的类型。由于 replace
的第二个参数的预期类型是 string
我们不允许传递 undefined
.
常量 value
具有 string | undefined
类型,这就是为什么它不允许作为参数。我们需要确保它是一个 string
,这就是我添加三元运算符的原因。
版本forEach
:
export interface IHtmlProperties {
website?: string
favIcon?: string;
}
function getHtml(htmlTemplate: string, properties: IHtmlProperties) {
const options: IHtmlProperties = {
website: properties.website,
favIcon: properties.favIcon
};
let html = htmlTemplate;
(Object.keys(options) as Array<keyof IHtmlProperties>)
.forEach((key) => {
const value = options[key];
if (value) {
html.replace(`{{${key}}}`, value)
}
});
return html;
}