admin管理员组

文章数量:1405564

I'm trying to make a pluggable function, based on this.

export type PropertyDescriptorValue = (PropertyDescriptor & ThisType<unknown>)['value'];
export type PropertyConfig<K extends PropertyKey> = { [p in K]: PropertyDescriptorValue };
export function defineProperty<T, K extends PropertyKey>(
    o: T,
    p: K,
    attributes: PropertyDescriptor & ThisType<unknown>,
): asserts o is T & PropertyConfig<K> {
    Object.defineProperty<T>(o, p, attributes);
}

export const mylib = () => {};

defineProperty(mylib, 'teste', {
    writable: false,
    value(a: number, b: number) {
        return a + b;
    },
})

console.info("a:", mylib.teste(1, 1)) // 2

The code above works properly, but I'm thinking of something more like this:

export type PropertyDescriptorValue = (PropertyDescriptor & ThisType<unknown>)['value'];
export type PropertyConfig<K extends PropertyKey> = { [p in K]: PropertyDescriptorValue };
export function register<T>(o: T) {
    return <K extends PropertyKey>(
        p: K,
        attributes: PropertyDescriptor & ThisType<unknown>,
    ): asserts o is T & PropertyConfig<K> => { // but, how may I assert this `o` here?
        Object.defineProperty<T>(o, p, attributes);
    }
}

export const mylib = () => {};

mylib.register = register(mylib)

mylib.register('teste', {
    writable: false,
    value(a: number, b: number) {
        return a + b;
    },
})

console.info("a:", mylib.teste(1, 1)) // 2

Is it possible to infer new methods? I think it is, but I'm not sure anymore.

I'm trying to make a pluggable function, based on this.

export type PropertyDescriptorValue = (PropertyDescriptor & ThisType<unknown>)['value'];
export type PropertyConfig<K extends PropertyKey> = { [p in K]: PropertyDescriptorValue };
export function defineProperty<T, K extends PropertyKey>(
    o: T,
    p: K,
    attributes: PropertyDescriptor & ThisType<unknown>,
): asserts o is T & PropertyConfig<K> {
    Object.defineProperty<T>(o, p, attributes);
}

export const mylib = () => {};

defineProperty(mylib, 'teste', {
    writable: false,
    value(a: number, b: number) {
        return a + b;
    },
})

console.info("a:", mylib.teste(1, 1)) // 2

The code above works properly, but I'm thinking of something more like this:

export type PropertyDescriptorValue = (PropertyDescriptor & ThisType<unknown>)['value'];
export type PropertyConfig<K extends PropertyKey> = { [p in K]: PropertyDescriptorValue };
export function register<T>(o: T) {
    return <K extends PropertyKey>(
        p: K,
        attributes: PropertyDescriptor & ThisType<unknown>,
    ): asserts o is T & PropertyConfig<K> => { // but, how may I assert this `o` here?
        Object.defineProperty<T>(o, p, attributes);
    }
}

export const mylib = () => {};

mylib.register = register(mylib)

mylib.register('teste', {
    writable: false,
    value(a: number, b: number) {
        return a + b;
    },
})

console.info("a:", mylib.teste(1, 1)) // 2

Is it possible to infer new methods? I think it is, but I'm not sure anymore.

Share edited Mar 8 at 0:38 Adrian Miranda asked Mar 7 at 21:58 Adrian MirandaAdrian Miranda 3384 silver badges13 bronze badges 3
  • Is this a minimal reproducible example? The "based on this" section seems to have syntax errors and maybe other typos (what's defineProperty?). Please edit so we can copy and paste into our own IDEs and immediately get to work on it without having to fix things to get to the starting line. – jcalz Commented Mar 7 at 22:31
  • (see prev comment and pls make requested edit) Maybe this is a duplicate of stackoverflow/questions/77366812/…? Can you check? – jcalz Commented Mar 7 at 22:38
  • Sorry about that, in the editing I accidentally cut and pasted something wrong, but I’ve already fixed it, thank you! – Adrian Miranda Commented Mar 8 at 15:25
Add a comment  | 

1 Answer 1

Reset to default 2

You can use asserts keyword to assert presence of new properties, but assertion requires explicit annotation so there's some small boiler plating. I guess it could be optimized, but you have an idea:

Playground

function register<T extends object>(obj: T){
    function register<K extends PropertyKey, T extends {}, P extends PropertyDescriptor>(
        this: T,
        p: K,
        attributes: P,
    ): asserts this is T & { [p in K]: P['value']}{ 
        Object.defineProperty<T>(this, p, attributes);
    }
    return Object.assign(obj, {register}) as T & {register: typeof register} 
}

type WithRegister<T extends object> = ReturnType<typeof register<T>>;

const base = () => {};
const mylib: WithRegister<typeof base> = register(base);

mylib.register('teste', {
    writable: false,
    value(a: number, b: number) {
        return a + b;
    },
})

console.info("a:", mylib.teste(1, 1)) // (property) teste: (a: number, b: number) => number

本文标签: typescriptInfer new propertiesStack Overflow