Definitelytyped: [D3] Refinar Definições/Redução da Dívida Técnica

Criado em 13 fev. 2018  ·  45Comentários  ·  Fonte: DefinitelyTyped/DefinitelyTyped

  • [x] [Mencione](https://github.com/blog/821-mention-somebody-they-re-notified) os autores (veja Definitions by: em index.d.ts ) para que eles possam responder.

    • Autores: @tomwanzek @gustavderdrache @Ledragon

Estou criando este problema como um problema de rastreamento de substituição para #11365, #11365 e #17846.

A seguir está uma tabela para rastrear refinamentos/dívidas técnicas relacionadas às definições do módulo D3.

  • JSDoc: comentários JSDoc completos, incluindo parâmetros e explicação genérica
  • strictNullChecks: Validado para strictNullChecks e opção do compilador definida como true
  • strictFunctionTypes: Validado para strictFunctionTypes e opção do compilador definida como true
  • TS 2.3: Versão mínima do TS 2.3 e definições usam padrões para genéricos

| Definição| JSDoc | strictNullChecks | strictFunctionTypes | TS 2.3 |
| --- | --- | --- | --- | --- |
| d3 | N/A | 🔲 | 🔲 | ✅ |
| matriz d3 | 🔲 | ✅ | 🔲 | 🔲 |
| eixo d3 | ✅ | ✅ | ✅ | ✅ |
| d3-escova | ✅ | ✅ | 🔲 | 🔲 |
| acorde d3 | ✅ | ✅ | 🔲 | 🔲 |
| coleção d3 | ✅ | ✅ | ✅ | ✅ |
| d3-cor | 🔲 | ✅ | ✅ | ✅ |
| d3-contorno | ✅ | ✅ | ✅ | 🔲 |
| d3-despacho | ✅ | ✅ | ✅ | ✅ |
| d3-arrastar | ✅ | ✅ | 🔲 | 🔲 |
| d3-dsv | ✅ | ✅ | 🔲 | 🔲 |
| d3-facilidade | ✅ | ✅ | 🔲 | 🔲 |
| d3-busca | ✅ | ✅ | 🔲 | 🔲 |
| d3-força | ✅ | ✅ | 🔲 | 🔲 |
| formato d3 | ✅ | ✅ | ✅ | ✅ |
| d3-geo | ✅ | ✅ | ✅ | ✅ |
| d3-hexbin | 🔲 | 🔲 | 🔲 | 🔲 |
| d3-hierarquia | 🔲 | 🔲 | 🔲 | 🔲 |
| d3-interpolar | 🔲 | 🔲 | 🔲 | 🔲 |
| d3-caminho | ✅ | ✅ | 🔲 | 🔲 |
| d3-polígono | ✅ | ✅ | ✅ | ✅ |
| d3-quadtree | 🔲 | 🔲 | 🔲 | 🔲 |
| d3-fila | ✅ | 🔲 | 🔲 | 🔲 |
| d3-aleatório | ✅ | ✅ | 🔲 | 🔲 |
| d3-pedido | 🔲 | 🔲 | 🔲 | 🔲 |
| d3-sankey | ✅ | ✅ | 🔲 | 🔲 |
| escala d3 | ✅ | ✅ | 🔲 | 🔲 |
| d3-escala-cromática | ✅ | ✅ | 🔲 | 🔲 |
| d3-seleção | ✅ | ✅ | ✅ | 🔲 |
| d3-seleção-multi | ✅ | ✅ | 🔲 | 🔲 |
| forma d3 | ✅ | ✅ | 🔲 | 🔲 |
| d3-tempo | ✅ | ✅ | 🔲 | 🔲 |
| formato de hora d3 | ✅ | ✅ | 🔲 | 🔲 |
| d3-temporizador | ✅ | 🔲 | 🔲 | 🔲 |
| d3-transição | ✅ | ✅ | 🔲 | 🔲 |
| d3-voronoi | ✅ | 🔲 | 🔲 | 🔲 |
| d3-zoom | ✅ | ✅ | 🔲 | 🔲 |

"Fora" da manutenção da equipe principal:

| Módulo | JSDoc | strictNullChecks | strictFunctionTypes | TS 2.3 |
| --- | --- | --- | --- | --- |
| d3-hsv | ✅ | ✅ | ✅ | ✅ |

Comentários muito úteis

@denisname 💯 @gustavderdrache @ledragon Obrigado por todo o trabalho duro nos últimos tempos. Atualizei a tabela de rastreamento, já está muito mais bonita! porque uma bela tabela de rastreamento é o que pretendemos aqui :smile:

Todos 45 comentários

@gustavderdrache @Ledragon Acima consolidei as poucas tarefas pendentes para ronda da obra que é o conjunto de definições D3.

Uma pergunta-chave: queremos atualizar todas as definições de forma consistente para uma restrição TS >=2.3 e, no processo, remover algumas das sobrecargas de funções/métodos usando atribuições padrão para genéricos?
Percebi que (inadvertidamente) algumas das definições já possuem a restrição // TypeScript Version: 2.3 no cabeçalho de definições. Por exemplo , d3-geo , que usa as definições geoJson . Estes já usam padrões genéricos.

Seus pensamentos sobre este assunto seriam mais do que bem-vindos.

Entenda isso você tem que estudá-lo

Se estiver implementando um TS 2.3 mínimo, também devemos poder usar o tipo object em vez de any , quando apropriado. Veio com TS 2.2. Se bem me lembro, havia um punhado de oportunidades com interpoladores de objetos e na coleção d3.

Primeiros pensamentos:

  • Devido ao bug de falta de memória que você encontrou, não devemos aplicar o 2.4 em todos os lugares?
  • Eu tenho uma filial com strictNullChecks e strictFunctionTypes aqui . Vou atualizá-lo e enviar um PR. Eu pensei que sim, mas não parece

Eu tenho que aprender sobre genéricos padrão antes de ter uma opinião sobre isso :p

Com o TS 2.3, estamos olhando para um lançamento em abril de 2017.
O TS 2.4 foi lançado em junho de 2017.

Portanto, a grande questão é: estamos criando problemas em uma grande ou insignificante/nenhuma parte da base instalada ao forçar um mínimo de 2,4 (em vez de 2,3)?

Eu acho que um dos desafios adicionados é que não temos um Changelog per se para sinalizar alterações potencialmente significativas em como as definições D3 são consumidas. E a desconexão óbvia, que uma mudança de ruptura pode ocorrer em uma versão secundária das definições, uma vez que elas estão alinhadas com o ciclo de lançamento D3 subjacente.

@gustavderdrache Qual é a sua opinião sobre o TS 2.4 como o novo mínimo?

Como visto na PR #23654, parecemos cascatear rapidamente quando vamos para o TS 2.4 (mesmo que seja apenas impor a restrição por causa do DT sem usar nenhum recurso do TS 2.4, como enumerações de string).

Para maior clareza, de acordo com o novo PR #23724, podemos continuar usando simplesmente o TS 2.3. Não há necessidade de avançar com o TS 2.4 a partir de agora.

@Ledragon Se você deseja abrir o PR que já tinha pendente em seu fork d3-geo local, podemos trabalhar para marcar as caixas acima.

Na verdade, não consigo testá-lo localmente... Então, acho que posso enviá-lo, mas não acho que passará nos testes do travis. Eu vou em frente e ver

23794 enviado - não é meu trabalho de maior orgulho, vamos ver como fica...

Ok, então o problema é o seguinte: testes d3-geo falham no TS 2.3, então tentei configurar a versão para 2.4. No entanto, d3 global está definido como TS 2.3, então isso também não funciona. Alguma dica de como proceder?

Vou olhar para o PR do g3-geo e colocarei quaisquer comentários de revisão para mantê-los focados. Ao contrário do bug OoM que tive com d3-collection , temos uma mensagem de erro adequada para trabalhar 😄

Acabei de enviar #24118 para atualizar d3-contour para 1.2.0
Percebi que os tipos d3-contour já estão em TS2.3 e têm strictNullChecks e strictFunctionTypes definidos como verdadeiros :-)

Obrigado por ficar por dentro do d3-contour , me fez notar que por algum motivo estranho eu não tinha o repositório em "Assistindo". Mudou isso! :sorrir:

Dará uma olhada no PR em breve.

Estou trabalhando no eixo d3 e no formato d3. Estou quase pronto. Mas tire algumas dúvidas...

No formato d3, quero usar a mesma interface Numeric que no d3-array:

interface Numeric {
    valueOf(): number;
}

Mas ao fazer isso, nas definições globais do d3, logicamente tenho o erro: Module 'd3-array' has already exported a member named 'Numeric'. Existe um lugar para colocar tipos compartilhados para bibliotecas d3?

Também em algumas definições d3 (interpolar, scale, shape) você pode encontrar o tipo de união number | { valueOf(): number } . { valueOf(): number } não é suficiente?

@denisname Obrigado por se voluntariar para d3-axis , d3-format e mais tarde d3-array !!!

Para suas perguntas acima:

(1) Como regra fundamental para escrever as definições para os módulos d3-xxx , as definições nunca devem introduzir dependências que não existam entre os módulos D3 correspondentes subjacentes. Por exemplo d3-axis não depende de d3-array , portanto, o arquivo de definição index.ts para d3-axis não deve ser importado de d3-array . Isso garante o acoplamento fraco correspondente às fontes JS. Portanto, em caso de dúvida, verifique a propriedade dependencies do package.json do módulo D3 subjacente _Nota: Você pode importar de qualquer pacote no arquivo d3-xxx-test.ts , isso é até uma boa prática que seguimos em vários pacotes para testes de "integração". Ou seja, pode não haver dependência formal entre dois pacotes, mas os membros de um são "naturalmente" usados ​​como entrada para o outro. Por exemplo, estamos usando d3-selection em um teste em d3-chord para garantir que um caminho de acorde possa ser passado para um setter de atributo de seleção sem problemas._

(2) Você está correto, que a interface Numeric não pode ser declarada novamente em nenhum outro módulo D3, que não pode importar de d3-array em conformidade com a regra (1).

(3) { valueOf(): number } não é suficiente? Tecnicamente, sim. Praticamente, o tipo de interseção, embora tenha alguma redundância, é declarativamente provavelmente mais claro para muitos usuários humanos. Ou seja, mostra que number é um tipo válido à primeira vista sem acrobacias mentais. :piscadela:

Sobre d3-color, por que os prototype estão todos comentados? Isso foi feito neste commit por @tomwanzek.

Com os protótipos ajustados, poderíamos usar instanceof diretamente, sem a necessidade de uma função typeguard:

let cRGB: d3.RGBColor;
let cHSL: d3.HSLColor;

const c: d3.RGBColor | d3.HSLColor = d3.color("steelblue");

if (c instanceof d3.rgb) {
    cRGB = c;
} else {
    cHSL = c;
}

@denisname Eu hesitei em definir prototype como parte da API publicada em uma interface, parece muito hacky.

Pelo que entendi da especificação de guardas de tipo de hoje. Isso agora é considerado como uma _construção_ válida. Veja o item da lista:

Um tipo guard da forma x instanceof C , onde x não é do tipo Any, C é de um subtipo do tipo global 'Function' e C tem uma propriedade chamada 'protótipo' [...]

Eu gostaria de propor uma versão strictNullChecks de d3-color . O que é apenas uma mudança de uma linha. Esta seria uma oportunidade para adicionar prototype também.

Do meu próprio teste, você precisa da propriedade prototype ou de uma declaração new(): T para instanceof para restringir adequadamente o tipo. Eu usei a variação new(): Color nas tipagens v3, e pode ser útil se esse idioma ainda for suportado pelo D3v4 e superior.

Como qualquer um parece bom, acho que podemos seguir a convenção v3 para continuidade. Ótimo trabalho, ambos.

@gustavderdrache

Meu entendimento de por que funciona no d3 v3 é que o tipo de retorno de new() é sempre o mesmo que o tipo prototype . Mas em d3 v4 também temos:

export const color: ColorFactory;
export interface ColorFactory extends Function {
    (cssColorSpecifier: string): RGBColor | HSLColor;
    prototype: Color; // and not RGBColor | HSLColor !
}

De fato, d3.lab(0,0,0) instanceof d3.color é verdade. Portanto, se alterarmos essa interface para:

export const color: ColorFactory;
export interface ColorFactory extends Function {
    (cssColorSpecifier: string): RGBColor | HSLColor;
    new (cssColorSpecifier: string): RGBColor | HSLColor;
}

Não temos como prototype para ColorFactory o tipo Color . E o código a seguir falha ao compilar, enquanto não deveria.

declare let l: d3.LabColor | null;
declare let c: d3.Color;
declare let nil: null;

if (l instanceof d3.color) {
    c = l; // l is not inferred as `d3.LabColor`...
} else {
    nil = l; // fail, l is a `d3.LabColor | null` should be a `null`
}

qual e sua OPINIAO? Existe uma maneira de fazê-lo funcionar com new ? Obrigado.

Parece que a propriedade prototype para color() deve ser Color e não RGBColor | HSLColor , com base em alguns testes:

> d3.color.prototype === d3.rgb.prototype
false
> d3.rgb.prototype instanceof d3.color
true

A função color() retorna cores RGB ou HSL, mas seu protótipo é um supertipo dos outros espaços de cores.

@denisname @Ledragon @gustavderdrache já que todos vocês estão neste tópico, apenas como um breve FYI: pretendo acompanhar os itens abertos que você conhece neste fim de semana.

Tudo bem, d3-geo está fora da porta (obrigado @ledragon) e eu comentei sobre o PR infelizmente fechado de @denisname por d3-format e d3-axis em relação à reabertura.

Como nota geral, eu recomendaria que @denisname fosse adicionado como outro mantenedor das definições, nas quais eles funcionam.

Eu poderia dar uma olhada em d3-color seguir e juntar-se a ele com uma atualização para 1.1.0 . Devemos abrir um problema separado para esta atualização?

Além disso, bem-vindo a bordo @denisname !

@Ledragon Obrigado.

Eu tenho uma atualização pronta para d3-color (sem lhc e gray ainda). Eu só estou preso por um pequeno problema.

@gustavderdrache disse:

A função color() retorna cores RGB ou HSL, mas seu protótipo é um supertipo dos outros espaços de cores.

De fato e isso pode ser _digitado_ facilmente, veja a primeira interface no meu comentário . Mas @tomwanzek propôs usar apenas new() e evitar prototype . Acho que neste caso específico não é possível. Não?...

Depois de brincar um pouco mais, estou vendo o problema. Você pode definir new(): Color na interface ColorConstructor , mas na verdade não cobre o valor de retorno da função:

declare namespace d3 {
  interface Color {
    // I forgot what was on the Color interface
    // This property exists just to make Color incompatible with {}
    __isColor: never;
    toString(): string;
  }

  interface RGBColor extends Color {
    r: number;
    g: number;
    b: number;
  }

  interface HSLColor extends Color {
    h: number;
    s: number;
    l: number;
  }

  interface LABColor extends Color {
    l: number;
    a: number;
    b: number;
  }

  interface ColorConstructor {
    (specifier: string): RGBColor | HSLColor;
    new(specifier: string): Color; // <- TS uses this for narrowing with instanceof
  }

  const color: ColorConstructor;
}

declare let l: d3.LABColor | null;
declare let c: d3.Color;
declare let nil: null;

if (l instanceof d3.color) {
  // Succeeds with l: d3.LABColor
  c = l;
} else {
  // Succeeds with l: null
  nil = l;
}

Concluindo: acho que temos que expor a propriedade prototype , porque é realmente a única maneira de cobrir o comportamento correto do construtor e do teste instanceof :

  interface ColorConstructor {
    (specifier: string): RGBColor | HSLColor;
    new(specifier: string): RGBColor | HSLColor;

    readonly prototype: Color; 
  }

Desculpe, pela demora em voltar a isso. Sinta-se livre para ir com prototype , no passado, foi meu primeiro impulso para abordar o instanceof também. Ele apenas "sentiu" hacky, mas como é considerado uma prática aceitável, e se a continuidade com o uso de new() como em D3v3 não é uma opção...Vamos com o que funciona!

@tomwanzek você poderia atualizar a tabela de rastreamento.

Um ✅ deve ser definido nas colunas strictNullChecks strictFunctionTypes e TS 2.3 para bibliotecas d3-axis , d3-color , d3-dispatch , d3-format , d3-polygon e d3-hsv .

Além disso, um ✅ deve ser definido na coluna JSDoc para d3-dispatch , d3-polygon e d3-hsv .

Obrigado

Há um erro de digitação na interface $ d3-geo GeoIdentityTranform . Deve ser GeoIdentityTransform (com s ). Posso corrigir? Alguma preocupação sobre compatibilidade com versões anteriores?

@denisname para d3-geo s GeoIdentityTranform , acho que poderíamos fazer o seguinte:

  • Renomeie a interface com erros ortográficos (Grande captura!) (incluindo seu uso como um tipo de retorno de geoIdentity()
  • Por enquanto adicione
/**
 * <strong i="13">@deprecated</strong> Misspelled name. Use GeoIdentityTransform.
 */
export type GeoIdentityTranform = GeoIdentityTransform;
  • Em um estágio conveniente posterior, remova completamente o tipo incorreto.

@denisname 💯 @gustavderdrache @ledragon Obrigado por todo o trabalho duro nos últimos tempos. Atualizei a tabela de rastreamento, já está muito mais bonita! porque uma bela tabela de rastreamento é o que pretendemos aqui :smile:

porque uma bela tabela de rastreamento é o que estamos buscando aqui

Absolutamente! As definições de tipo aprimoradas são apenas um efeito colateral agradável.

Algum de vocês está trabalhando em definições específicas agora para a conclusão da dívida técnica? Enquanto d3-array está em processo. Eu abordaria o strictFunctionTypes na transição d3 ao lado para trazê-lo à paridade com a seleção d3 . Apenas esperando o #25805 ser mesclado.

Não caixa eletrônico. Vou deixar vocês saberem se e quando eu fizer

Trabalhando em #25582 para poder carimbar o pacote global 5.2.0

Eu tenho uma atualização para d3-hierarchy pronta (strict e jsDoc).
Também trabalhando em d3-dsv e d3-fetch (ts 2.3).

@denisname @tomwanzek @gustavderdrache
Devemos nos concentrar nisso ou em atualizar o d3 para a versão mais recente? Estamos agora 5 versões menores atrás do pacote global (embora todos os sub-pacotes estejam prontos para 5.2.0 eu acho). Devo abrir um problema separado para rastrear o status global do pacote?

@Ledragon Vou acompanhar os PRs abertos hoje à noite e analisar todas as definições do módulo D3 para moeda. Se houver algum atraso, criarei um problema de rastreamento para ajustá-lo. Quanto às prioridades, concordo que a moeda deve ter prioridade sobre a redução da dívida técnica.

Desculpe poluir este tópico, estou voltando ao D3.js agora para um novo projeto.

/** <strong i="6">@type</strong> {SyncBailHook<Compilation>} */
shouldEmit: new SyncBailHook(["compilation"]),

No webpack, eles começaram a usá-lo para verificar JavaScript com o compilador TypeScript. A grande vantagem são as definições de digitação ao lado do código real.
https://github.com/webpack/webpack/blob/master/lib/Compiler.js#L51

Olá @phil-lgr
Houve uma discussão sobre o rastreador de problemas d3 não muito tempo atrás, e ele não parecia estar no topo da lista de prioridades (ou seja, Mike Bostock preferiu focar no desenvolvimento da própria biblioteca ao invés das tipagens). Não consigo encontrar um link para o tópico. Talvez a questão possa ser levantada novamente graças a essas novas informações, mas não acho provável que isso aconteça

@tomwanzek você poderia atualizar a tabela de rastreamento.

Um ✅ deve ser definido nas colunas strictNullChecks strictFunctionTypes e TS 2.3 para bibliotecas d3-array , d3-array , d3-dsv , d3-fetch , d3-hexbin , d3-hierarchy , d3-interpolate , d3-quadtree , d3-queue , d3-request , d3-timer e d3-voronoi .

Além disso, um ✅ deve ser definido na coluna JSDoc para d3-color , d3-hexbin , d3-hierarchy , d3-interpolate e d3-quadtree .

Obrigado

Esta página foi útil?
0 / 5 - 0 avaliações