Answer the question
In order to leave comments, you need to log in
How to overwrite HTMLElement fields with fields from input object in Typescript?
Good afternoon! The goal is to create a function that takes a tag, options to rewrite fields, and returns a ready-to-use object. But the typescript throws spokes into the wheels, I don’t understand why. I am not familiar with the typescript, I googled the type that pulls out the fields allowed for writing from the object, it seems like it should work, but still a strange error is issued. How to fix the error?
type IfEquals<X, Y, A=X, B=never> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;
type WritableKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];
type ReadonlyKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];
type WritableFields = Pick<HTMLElement, WritableKeys<HTMLElement>>
export function createElement(tag: string, options?: WritableFields): HTMLElement {
let element = document.createElement(tag)
if (options) {
// assign options
let option: keyof WritableFields
for (option in options) {
element[option] = options[option] // Type 'undefined' is not assignable to type 'never'
}
}
return element
}
Answer the question
In order to leave comments, you need to log in
Yab did this:
type WritableFields<T> = Partial<Pick<T, WritableKeys<T>>>;
export function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, options?: WritableFields<HTMLElementTagNameMap[K]>): HTMLElementTagNameMap[K] {
let element = document.createElement(tag)
if (options) {
// assign options
Object.assign(element, options);
}
return element
}
type WritableFields<T> = Partial<Pick<T, WritableKeys<T>>>;
export function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, options?: WritableFields<HTMLElementTagNameMap[K]>): HTMLElementTagNameMap[K] {
let element = document.createElement(tag)
if (options) {
// assign options
let option: keyof typeof options;
for (option in options) {
element[option] = options[option]!; // ! - потому что теоретически ты можешь передать undefined явно, но морочиться с этим не стоит
}
}
return element
}
interface Foo {
foo: number;
}
there's nothing stopping you from telling him{
foo: 1,
bar: 2
}
, because this object extends the Foo interface and, accordingly, satisfies it. It turns out that inside the typescript function there is no way to be sure that the keys specified in the interface are ALL keys, which means that it cannot be sure that something superfluous will not be assigned when iterating and assigning. (This is not to mention prototypes, getters, etc.) Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question