According to the documentation for typescript: https://www.typescriptlang.org/docs/handbook/2/keyof-types.html a type which is the keyof an object should be a union of all the keys in the object. Given that, I should expect the MetaObjectKey type to be "title" | "description" | "image" | "url" | "site_name" | "type"
This however does not seem to be the case as I cast the result of const key = ogTags[i].split(':')[1] as MetaObjectKey; as a MetaObject key yet still get the typescript error on the next line stating Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'. when I try to assign to parsedMetaObject. What gives? This seems to be completely out of line with the documentation and potentially buggy.
Code sandbox link included as well: https://codesandbox.io/s/typescript-forked-pt2t9z?file=/src/add.ts
import { HTMLElement, parse } from 'node-html-parser';
interface MetaObject {
title: string;
description: string;
image: string;
url: string;
site_name: string;
type: string;
}
type MetaObjectKey = keyof MetaObject;
const ogTags = [
'og:title',
'og:description',
'og:image',
'og:url',
'og:site_name',
'og:type'
];
export const generateHTMLNodes: (data: string) => HTMLElement = (data) =>
parse(data);
export const extractMetaTagsFromHTMLRoot: (
rootElement: HTMLElement
) => MetaObject = (rootElement) => {
const allMetaNodes = rootElement.querySelectorAll('meta');
const parsedMetaObject: MetaObject = {
title: '',
description: '',
image: '',
url: '',
site_name: '',
type: ''
};
allMetaNodes.forEach((aMN) => {
const i = ogTags.findIndex((e) => e === aMN.getAttribute('name'));
if (i >= 0) {
const key = ogTags[i].split(':')[1] as MetaObjectKey;
parsedMetaObject[key] = aMN.getAttribute('content');
}
});
return parsedMetaObject;
};
export default generateHTMLNodes;
CodePudding user response:
I'm an idiot. The typescript compiler wasn't complaining about the key, it was complaining about the return value of getAttribute being string | undefined. I updated the following to ensure that string is assigned.
allMetaNodes.forEach((aMN) => {
const i = ogTags.findIndex((e) => e === aMN.getAttribute('name'));
if (i >= 0) {
const key = ogTags[i].split(':')[1] as MetaObjectKey;
parsedMetaObject[key] = aMN.getAttribute('content') ?? '';
}
});
CodePudding user response:
As all value of the MetaObject
is string, it need to be asserted as might be aMN.getAttribute('content') would result in undefined or null.
What you need to add is to assert for string.
parsedMetaObject[key] = aMN.getAttribute('content') as string;
OR in the if condition add this condition too.
if (i >= 0 && aMN.getAttribute('content'))