在類上使用代理,同時保持對現有屬性和類類型的訪問

錯誤的

為了了解 Proxy 的工作原理,我想嘗試製作一個 Proxied 類,該類可以處理任何屬性名稱,即使是類中不存在的那些,同時仍然保持對舊屬性的訪問。當一個類被代理時,我認為 Typescript 會讓你在本地執行此操作(因為這畢竟是代理用例之一),但我遺憾地發現情況並非如此。當我嘗試做這樣的事情時:

const handler = {
    get: (target: any, key: string) => {
        return key;
    },

    set: (target: any, key: string, value: any) => {
        console.log(target, key, value);
        return true;
    }
};
class ProxTest {
    private storage: {[key: string]: any} = {};
    public a: number;

    constructor() {
        return new Proxy(this, handler);
    }
}

const c = new ProxTest();
c.val = "b"; //Gives error

嘗試訪問時出錯c.val我找到了一個“解決方案”,即使用“索引簽名”並將 //@ts-ignore 添加到所有其他屬性。

const handler = {
    get: (target: any, key: string) => {
        return key;
    },

    set: (target: any, key: string, value: any) => {
        console.log(target, key, value);
        return true;
    }
};
class ProxTest {
    //@ts-ignore
    private storage: {[key: string]: any} = {};
    //@ts-ignore
    public a: number;
    [key: string]: any;

    constructor() {
        return new Proxy(this, handler);
    }
}

const c = new ProxTest();
c.val = "b";

這是迄今為止我找到的唯一解決方案,老實說我並不喜歡它。有沒有其他方法可以做到這一點?

需要明確的是,這段代碼只是一般問題的一個例子(不能在代理對像上使用任意命名的屬性),它的形狀或形式與我實際使用的某些代碼沒有任何關係。但是因為這似乎是在打字稿中使用代理時應該能夠做的事情,所以我想找到一個通用的解決方案

錯誤的

所以,根據評論,我誤解了 Proxy 的工作方式,我認為它像 PHP 魔術方法一樣工作(也就是說,只有在嘗試訪問未知屬性時才會觸發 get/set 陷阱),而不是它適用於所有屬性,甚至那些已經存在於對像中的。
我假設打字稿會自動檢測一個代理類,並讓您像代理之前一樣使用該類的正常值,而在嘗試訪問未知屬性時它不會出錯,這可能就是我不能自己做的原因清楚我在問什麼。
默認情況下,當使用 Proxy 時,typescript 會將類型更改為“any”,這當然可以讓您在對像上使用任何類型的屬性而不會出錯,代價是無法直接訪問現有屬性(這是實際上與 javascript 一致,因為當您代理一個類並聲明 get/set 時,一切都會通過這些方法)

所以,我真正想要實現的是有一個代理類,我仍然可以訪問已經存在的屬性,並且 typescript 可以正確推斷已經存在的屬性的類型,同時在嘗試訪問不存在的屬性時仍然沒有錯誤. 我想出了這個解決方案:

interface ProxTestStorage extends ProxTestConstructor {
    [key: string]: any;
}

interface ProxTestConstructor {
    new(): ProxTestImpl & ProxTestStorage;
}

class ProxTestImpl {
    protected storage: {[key: string]: any} = {};
    public a: number = 3;
}

const handler = {
    get: (target: any, key: string) => {
        console.log(target, key);
        return Reflect.get(key in target ? target : target.storage, key);
    },

    set: (target: any, key: string, value: any) => {
        console.log(target, key);
        return Reflect.set(key in target ? target : target.storage, key, value);
    }
};

const ProxTest = ProxTestImpl as any as ProxTestImpl & ProxTestStorage;
const c = new Proxy<typeof ProxTest>(new ProxTest(), handler);
c.val = "b"; //No error, type is any
c.a = 2; //No error, type is number

console.log(c); // ...{a: 2, storage: {val: "b"}}...

當然 get 和 set 需要正確實現才能讓您訪問現有屬性(使用“in”的缺點是屬性需要初始化才能看到,但由於這“只是”理解代理的練習,我是好的)並且它們必須與您的類型的邏輯一致。通過聲明這樣的類型,我在使用 ProxTest 作為類型時必須使用“typeof ProxTest”(與普通類不同),但我想現在這是一個小問題,超出了我的問題範圍。

感謝@jcalz 的耐心:)

Este artigo é coletado da Internet.

Se houver alguma infração, entre em [email protected] Delete.

editar em
0

deixe-me dizer algumas palavras

0comentários
loginDepois de participar da revisão

Artigos relacionados

訪問類中的屬性

具有復雜屬性類型的對象字面常量的類型定義

使用 makestyles @mui 時,類型“字符串”上不存在屬性“”

輕鬆訪問靜態類python的屬性

無法為依賴類型的對象獲取未知的屬性“實現”

從超類方法訪問子類靜態屬性

如何訪問我的父類屬性而不在父類中初始化它?

AttributeError: 類型對象“數據庫”沒有屬性“scoreDB”

如何獲取屬性基於某種類型的類的所有屬性

訪問另一個 Java 類中的現有對象

複製另一種對像類型的 TypeScript 類型,但根據其原始類型條件更改屬性類型

“ToastrModule”類型上不存在屬性

類型上不存在屬性“精確”

類型“{}” useparams 上不存在屬性“abc”

正確的抽像類實現的屬性類型

使用計算屬性時如何設置類型?

如何使用Kafka中的屬性文件映射類型

試圖在 Discord 上運行聊天機器人但得到 AttributeError:類型對象“ChatBot”沒有屬性“請求”

屬性 XXX 不會在使用 Typescript 的“Computed”類型上退出

無法通過 JPA 訪問嵌入式類的屬性

JPA 繼承策略 JOINED:Connot 訪問超類屬性

TypeScript:創建根據值類型刪除接口/類的屬性的類型

對列表使用類型提示時 Pytest 失敗

什麼是類對象的類型,其中類實現了接口並擁有自己的新成員

打字稿:如何定義對象屬性的類型?

TS:通過變量獲取對象屬性的類型

unity 'GameObject' 類型的對像已被銷毀,但您仍在嘗試訪問它

如何將類屬性設置為類方法返回類型?

AWS CDK Typescript 問題:預期類型來自屬性“securityGroups”,該屬性在此處聲明為“InstanceProps”類型

TOP lista

  1. 1

    R Shiny: use HTML em funções (como textInput, checkboxGroupInput)

  2. 2

    O Chromium e o Firefox exibem as cores de maneira diferente e não sei qual deles está fazendo certo

  3. 3

    Como assinar digitalmente um documento PDF com assinatura e texto visíveis usando Java

  4. 4

    R Folheto. Dados de pontos de grupo em células para resumir muitos pontos de dados

  5. 5

    Gerenciar recurso shake de Windows Aero com barra de título personalizado

  6. 6

    Como obter dados API adequados para o aplicativo angular?

  7. 7

    UITextView não está exibindo texto longo

  8. 8

    Por que meus intervalos de confiança de 95% da minha regressão multivariada estão sendo plotados como uma linha de loess?

  9. 9

    Acessando relatório de campanhas na AdMob usando a API do Adsense

  10. 10

    Usando o plug-in Platform.js do Google

  11. 11

    Como posso modificar esse algoritmo de linha de visada para aceitar raios que passam pelos cantos?

  12. 12

    Dependência circular de diálogo personalizado

  13. 13

    Coloque uma caixa de texto HTML em uma imagem em uma posição fixa para site para desktop e celular

  14. 14

    iOS: como adicionar sombra projetada e sombra de traço no UIView?

  15. 15

    Como usar a caixa de diálogo de seleção de nomes com VBA para enviar e-mail para mais de um destinatário?

  16. 16

    Tabela CSS: barra de rolagem para a primeira coluna e largura automática para a coluna restante

  17. 17

    How to create dynamic navigation menu select from database using Codeigniter?

  18. 18

    Converter valores de linha SQL em colunas

  19. 19

    ChartJS, várias linhas no rótulo do gráfico de barras

  20. 20

    用@StyleableRes注释的getStyledAttributes。禁止警告

  21. 21

    não é possível adicionar dependência para com.google.android.gms.tasks.OnSuccessListener

quentelabel

Arquivo