AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-12393397

Grompok's questions

Martin Hope
Grompok
Asked: 2025-04-24 20:25:41 +0800 CST

Como descrever tipos corretamente ao criar e usar tipos derivados em TypeScript?

  • 7

Estou tentando criar uma integração com StompJS no meu projeto que reutiliza conexões e assinaturas para os mesmos tópicos. Estou usando TypeScript e estou tendo um problema em que o TS me dá um erro independentemente do que eu faça. Se eu o suprimir, o código funciona, mas isso parece trapaça.

const RESULT_PARSER_BY_TOPIC = {
    '/topic/user': (value: string): { id: string } => JSON.parse(value),
    '/topic/game': (value: string): string => value,
    '/topic/messages': (value: string): number => parseInt(value, 10),
} as const;
type Topic = keyof typeof RESULT_PARSER_BY_TOPIC;
type ResultParser<_Topic extends Topic> = typeof RESULT_PARSER_BY_TOPIC[_Topic];
type Result<_Topic extends Topic> = ReturnType<ResultParser<_Topic>>;
type Consumer<_Topic extends Topic> = (value: Result<_Topic>) => void;
type Unsubscribable = { unsubscribe: () => void };
type Subscription<_Topic extends Topic> = {
    producer: Promise<Unsubscribable>;
    consumers: Set<Consumer<_Topic>>;
};
export type Unsubscribe = () => void;

const SUBSCRIPTION_BY_TOPIC: Partial<{
    [_Topic in Topic]: Subscription<_Topic> // I think problem is with this type
}> = {};

export function subscribe<_Topic extends Topic>(
    topic: _Topic,
    callback: Consumer<_Topic>
): Unsubscribe {
    if (SUBSCRIPTION_BY_TOPIC[topic] === undefined) {
        SUBSCRIPTION_BY_TOPIC[topic] = { // <-- I get the error here 
            consumers: new Set(),
            producer: subscribeToTopic(topic)
        } as Subscription<_Topic>;
    }
    SUBSCRIPTION_BY_TOPIC[topic].consumers.add(callback);
    return () => {
        // some clean up logic...
    };
}

O objetivo de tudo isso é ter um método de assinatura fácil de usar. Ele deve validar se os parâmetros do tópico e do consumidor são compatíveis:

subscribe('/topic/user', (value) => {...}); // should infere that "value" is { id: string }
subscribe('/topic/game', (value) => {...}); // should infere that "value" is string

//if parameter mismatch there should be an error
subscribe('/topic/messages', (value: boolean) => {...}); // <- error: "(value: number) => void" expected

Mas recebo um erro de tipo ao tentar atribuir uma nova Assinatura ao mapeamento de assinaturas (isso ocorre quando alguém assina um novo tópico; caso contrário, reutilizo uma assinatura de tópico existente), que uso para rastrear se o tópico ainda tem assinantes ativos (na lógica de limpeza: se o último assinante cancelar a assinatura, eu cancelo a assinatura do tópico). O erro:

TS2322:
Type Subscription<_Topic> is not assignable to type Partial<{
    "/topic/user": Subscription<"/topic/user">;
    "/topic/game": Subscription<"/topic/game">;
    "/topic/messages": Subscription<"/topic/messages">;
}>[_Topic]

Type Subscription<_Topic> is not assignable to type Subscription<"/topic/user"> & Subscription<"/topic/game"> & Subscription<"/topic/messages">

Type Subscription<_Topic> is not assignable to type Subscription<"/topic/user">

Type _Topic is not assignable to type "/topic/user"

Type "/topic/user" | "/topic/game" | "/topic/messages" is not assignable to type "/topic/user"

Type "/topic/game" is not assignable to type "/topic/user"

Esta linha em particular me confunde:

Type Subscription<_Topic> is not assignable to type Subscription<"/topic/user"> & Subscription<"/topic/game"> & Subscription<"/topic/messages">

É como se o TS não conseguisse resolver que estou tentando atribuir um valor para uma chave específica, e não para qualquer chave no mapeamento.

Tentei converter diferentes partes do código para os tipos correspondentes, mas não obtive resultados significativos. O que "funcionou" foi alterar o tipo "Subscription.consumers" para Set<any>:

type Subscription = {
    producer: Promise<Unsubscribable>;
    consumers: Set<any>;
};

Mas eu gostaria de evitar isso, o objetivo deste projeto TS é que eu aprenda a usar melhor o TS.

typescript
  • 1 respostas
  • 59 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve