-
Notifications
You must be signed in to change notification settings - Fork 1
SupportedFeatures pt BR
🌐 Esta página em: English · Português
Este documento traz uma lista abrangente dos recursos de C#, APIs .NET e padrões suportados pelo compilador do eQuantic.UI.
Legenda
✅ Suporte completo: transpila para um comportamento JavaScript equivalente.
⚠️ Suporte parcial: funciona com ressalvas ou diferenças pequenas.❌ Sem suporte: lógica fundamentalmente incompatível (ex.: I/O bloqueante, ponteiros unsafe).
| Recurso | Status | Notas |
|---|---|---|
| Classes e structs | ✅ | Transpilados para classes ES6. |
| Interfaces | ✅ | Usadas na checagem de tipos do TypeScript (apagadas em runtime). |
| Enums | ✅ | Atravessam como o nome em camelCase (MainAlign.Start → 'start'). .ToString() e interpolação dão o nome do membro C# ("Start"), o mesmo texto que o servidor imprime. Desde 0.2.0-preview.15. |
| Genéricos | ✅ | Totalmente suportados (apagados em runtime). |
| Extension methods | ✅ | Resolvidos pelo Semantic Model e transpilados para chamadas diretas. |
| Async / await | ✅ | Mapeiam para async / await e Promise. |
| Expressões lambda | ✅ | Mapeiam para arrow functions () => {}. |
| Pattern matching | ✅ | Padrões is, padrões de propriedade, padrões recursivos. |
| Interpolação de string | ✅ | Mapeia para template literals `${var}`. |
| Null-coalescing | ✅ |
?? e ??= mapeados para os equivalentes JS. |
| Inicializadores de objeto | ✅ |
new Obj { Prop = 1 }. |
field (C# 14) |
✅ | Propriedades guardadas: o gêmeo ganha um slot $name (um nome que nenhum campo C# pode ter), um getter e o corpo do próprio acessor. |
Acessores init |
✅ | Emitidos como setter JS, porque um corpo de init é onde um tipo declara a invariante dele, e descartá-lo perderia a checagem no cliente. |
| Inicializadores de coleção | ✅ |
new List<int> { 1, 2 } mapeia para [1, 2]. |
| Desconstrução | ✅ |
var (a, b) = tuple mapeia para [a, b] = tuple. |
| Funções locais | ✅ | Transpiladas para funções internas. |
Records (with) |
✅ | Mapeia para spread de objeto { ...src, prop: val }. |
typeof |
✅ | Mapeia para o literal de string com o nome do tipo. |
Chamadas base |
✅ | Mapeiam para a palavra-chave super. |
cast e as |
✅ | Mapeiam para passagem/truncamento em JS. |
sizeof |
✅ | Mapeia para os tamanhos dos primitivos C#. |
| Métodos anônimos | ✅ |
delegate(...) { ... } mapeia para arrow functions. |
params |
✅ | Um parâmetro REST (...xs). As duas formas de chamada do C# funcionam: argumentos expandidos e um array passado inteiro, que é espalhado. Desde 0.2.0-preview.15. |
stackalloc |
✅ | Mapeia para typed arrays (ex.: Int32Array). |
yield return |
✅ | Mapeia para generator functions do JS (function*). |
lock |
Transpilado para um bloco sem efeito (JS é single-threaded). |
O compilador inclui estratégias especializadas para quase todos os métodos LINQ.
| Lógica | Métodos | Status |
|---|---|---|
| Filtragem |
Where, OfType
|
✅ |
| Projeção |
Select, SelectMany, Cast
|
✅ |
| Particionamento |
Skip, Take, SkipWhile, TakeWhile
|
✅ |
| Ordenação |
OrderBy, OrderByDescending, ThenBy, Reverse
|
✅ |
| Agregação |
Count, Sum, Min, Max, Average, Aggregate
|
✅ |
| Quantificadores |
Any, All, Contains
|
✅ |
| Conjuntos |
Distinct, DistinctBy, Union, Intersect, Except, Concat
|
✅ |
| Elementos |
First, FirstOrDefault, Single, Last, ElementAt
|
✅ |
| Utilitários |
SequenceEqual, DefaultIfEmpty
|
✅ |
| Conversão |
ToList, ToArray, ToDictionary, ToHashSet
|
✅ |
| Agrupamento/Join |
GroupBy, Join, Zip
|
✅ |
Mapeamos os tipos .NET comuns para os equivalentes em JavaScript.
| Tipo .NET | Equivalente JavaScript |
|---|---|
string |
String |
int, double, float
|
Number |
bool |
Boolean |
object |
Object |
dynamic |
any |
- ✅
Join,Format - ✅
IsNullOrEmpty,IsNullOrWhiteSpace - ✅
Split,Replace,Substring,Trim - ✅
ToLower,ToUpper,StartsWith,EndsWith
Os tipos temporais são respaldados por tipos compatíveis com precisão de tick (ticks de 100 ns,
calendário gregoriano proléptico, não o mapeamento com perda de new Date() / milissegundos
numéricos). Construtores, componentes, Add*, aritmética (-→TimeSpan), comparações e o
.ToString() invariante batem todos com o .NET; os valores atravessam o fio do SSR como strings
ISO-8601 / "c" e são hidratados de volta no tipo compatível.
Veja a tabela Cobertura e conformidade da BCL .NET abaixo para o detalhe por tipo.
- ✅
List<T>→ Array[]do JavaScript - ✅
Dictionary<TKey, TValue>→ objeto simples{}para chaves string/número/enum;$eq.collections.valueMappara chaves de record/struct/tupla (chaves de igualdade estrutural, então duas chaves iguais por valor colidem como no .NET). - ✅
HashSet<T>→Setdo JavaScript. - ✅
ContainsKey/TryGetValueperguntam pela chave própria do objeto, então um dicionário nunca responde por"constructor","toString"ou qualquer outra coisa emObject.prototype. Desde 0.2.0-preview.15. - ✅
Queue<T>,Stack<T>,LinkedList<T>,SortedSet<T>,SortedDictionary<K,V>,SortedList<K,V>→ coleções compatíveis do runtime, sob$eq.collections.*.
- ✅
Task,Task<T>→Promise. - ✅
Task.Delay→ wrapper desetTimeout. - ✅
Task.WhenAll,Task.WhenAny. ⚠️ Task.Runexecuta na thread principal (microtask), NÃO numa thread de fundo.
- ✅
Console.WriteLine→console.log. - ✅
Math.*(Min, Max, Abs, Round, etc.) →Math.*. - ✅
Guid(NewGuid,Empty,Parse) →crypto.randomUUID(). - ✅
Regex→RegExpdo JavaScript.
eQuantic.UI.Lucide / Heroicons / RadixIcons / TablerIcons / Phosphor / SimpleIcons / BootstrapIcons / Iconoir / ...
Propósito: conjuntos de ícones abrangentes. Contêm:
- Lógica de resolução de SVG
- Componentes de ícone especializados
- Implementação de
IIconProvider
| Pacote | Propósito | Status |
|---|---|---|
| eQuantic.UI.Charts (Apex/ChartJS) | Visualização de alta performance. | ✅ |
| eQuantic.UI.Lottie | Animações de alta performance. | ✅ |
| eQuantic.UI.Image | Otimizada (Lazy/Blur/Priority). | ✅ |
| eQuantic.UI.Tailwind | Integração de estilo padrão. | ✅ |
| Padrão | Interface | Descrição | Status |
|---|---|---|---|
| Gestão de metadados | IHandleMetadata |
Tags de SEO e elementos do head. | ✅ |
| Gestão de assets | IRequireAssets |
Injeção dinâmica de script/estilo. | ✅ |
| Server Actions | [ServerAction] |
RPC seguro do cliente para o servidor. | ✅ |
| Componentes compostos | N/A | Padrões de subcomponentes semânticos. | ✅ |
-
Código bloqueante:
- ❌
.Wait()e.Resultem Tasks NÃO são suportados. Você tem que usarawait. Bloquear a thread principal congela a interface do browser.
- ❌
-
Reflexão:
- ❌
System.Reflectioné largamente sem suporte. - ✅
typeof(T).Nameenameof(...)são constantes suportadas.
- ❌
-
Sistema de arquivos:
- ❌
System.IO(File,Directory) não é estritamente proibido, mas vai falhar em tempo de execução no browser. - Use Server Actions para lidar com operações de arquivo.
- ❌
-
Números:
- ✅
int/double/floatmapeiam para números do JS. A divisão inteira trunca (Math.trunc) e oMath.Roundusa arredondamento bancário (MidpointRounding.ToEven) pelo helper compatívelround. - ✅
decimalé exato de ponta a ponta: compilado para o tipo compatívelDecimaldo runtime (mantissa BigInt + escala), então0.1m + 0.2m == 0.3métrue. Decimais também atravessam o fio como strings JSON (EqJson) e são hidratados de volta emDecimalno cliente (o padrãoDecimaldo campo guia uma coerção que preserva o tipo, vejahydrate-value.ts), então os decimais vindos do servidor mantêm todos os 28 dígitos em vez de arredondar por um double. - ✅
long/ulongagora são exatos: compilados para BigInt do JS pelo helper compatívellong.9007199254740993L + 1Lé9007199254740994(um número JS comum arredondaria para…992). Literais viram BigInt (5L→5n); operandos de aritmética/comparação são embrulhados emlong()(que coagenumber/string→bigint) para que expressões mistas nunca lancem. No fio, inteiros de 64 bits atravessam como strings JSON (Server Actions + estado do SSR, viaEqJson) para que valores além de 2^53 sobrevivam à ida e volta. Outros sufixos de tipo numérico (1.5f,100u) são removidos.
- ✅
-
Segurança entre threads:
- Como o JS é single-threaded, instruções
locksão compiladas para fora (ignoradas). -
Thread.Sleepnão é suportado (useTask.Delay).
- Como o JS é single-threaded, instruções
A fidelidade da transpilação é imposta por um arnês de conformidade (tests/eQuantic.UI.Conformance.Tests):
cada caso roda a mesma expressão C# de dois jeitos, transpilada para JS (executada pelo Bun embarcado) e
avaliada diretamente em .NET (Roslyn scripting), e afirma resultados idênticos. Mais de 460 casos estão verdes.
(Mais recente: dicionários com chave de record via $eq.collections.valueMap.)
Isso cobre tanto expressões quanto blocos de instruções (controle de fluxo: if/for/foreach/while/switch/
try-catch-finally/funções locais; o bloco roda numa IIFE e o valor retornado é comparado).
Toda construção resolve por um de três mecanismos (veja docs/DOTNET-COVERAGE-PROGRAM.md):
-
Estratégia nativa: JS idiomático quando o runtime tem um equivalente.
-
Helper compatível com .NET no runtime: semântica .NET fiel onde o JS não tem nenhuma. O transpilador emite esses sob um único namespace
$eq(organizado por domínio), trazido com um import por módulo,import { $eq } from "@equantic/runtime"(resolvido pelo import map da página), em vez de N imports soltos de helpers, e$eq.*nunca pode colidir com um identificador do usuário no escopo gerado:-
$eq.num:dec(Decimal exato),long(Int64 via BigInt) -
$eq.math:round(arredondamento bancário) -
$eq.text:format(formatação de número/string),stringBuilder -
$eq.time:dateTime,timeSpan,dateOnly,timeOnly,dateTimeOffset -
$eq.enums:parse(nome de membro de enum) -
$eq.collections:queue(FIFO),stack(LIFO),valueMap(dicionário com chave estrutural),linkedList,sortedSet/sortedDictionary/sortedList(ordenados por chave) -
$eq.nullable:arith,cmp(operadoresNullable<T>elevados: aritmética que propaga nulo, relacional falso em nulo) -
$eq.equals: igualdade estrutural (por valor) para records/structs/tuplas (dá suporte a==,.Equals,Contains,Distinct) -
$eq.css:styleBuilder,classBuilder,joinClasses,whenClass(o subsistema de estilo)
-
-
Falhar no que não é suportado: uma construção sem representação possível em JS agora levanta um erro de build (com um código
EQestável) em vez de ser emitida verbatim em silêncio. Duas camadas:-
UnsupportedConstructStrategy(EQ2001): intrínsecos de referência tipada (__makeref,__refvalue,__reftype), tipos ponteiro, ponteiros de função. -
goto/goto case/goto default(EQ2002): sem equivalente em JS; reestruture com laços/condicionais. (Blocosunsafe/fixed/lockdesembrulham para o corpo deles, sendo olockum no-op single-threaded, e um rótulo solto cai para a instrução interna dele.) -
Fronteira cliente/servidor do
SemanticValidator(EQ21xx): chamadas aSystem.IO,System.Net.Http,System.Net.Sockets, EF Core /System.Data, threading do SO (Thread/Monitor/Mutex),Process,InteropServices(P/Invoke),Reflection.Emita partir de um componente cliente. (System.Threading.Tasksnão é proibido: async mapeia para Promise.) A correção é mover a chamada para um[ServerAction].
Qualquer outra construção que não bata em nenhuma estratégia é erro (
EQ1001para expressão,EQ1002para statement,EQ1003para o resto) e nada é emitido por ela. Antes passava verbatim com um aviso, o que dava uma build que sucedia e uma página que quebrava — recusar o que não consegue representar é justamente o ponto. Os diagnósticos saem na forma canônica do MSBuild, então falham odotnet builde a IDE linka. A lista completa está em Diagnósticos. -
| Área | Status | Notas |
|---|---|---|
| Aritmética / bitwise / comparação | ✅ | a divisão inteira trunca; %, deslocamentos, `& |
Math.* |
✅ |
Truncate→trunc, Ceiling→ceil, Round bancário pelo helper round
|
decimal |
✅ | exato via Decimal (literais + + - * / == != < > <= >=) |
| Constantes numéricas | ✅ |
int.MaxValue, double.Epsilon, … → literais |
Parsing / Convert.*
|
✅ |
int/double.Parse, bool.Parse, Convert.ToInt32/ToDouble/ToString/ToBoolean/…
|
| Strings | ✅ | Substring/IndexOf/Replace/Split/Pad/Trim(char)/Concat/Format/Join/IsNullOrEmpty/IsNullOrWhiteSpace; Equals/StartsWith/EndsWith/Contains/IndexOf cientes de StringComparison (Ordinal + IgnoreCase). Ordenação sensível à cultura (CompareTo) está fora de escopo. |
char.* |
✅ |
ToUpper/ToLower/IsDigit/IsLetter/IsWhiteSpace/… (cientes de Unicode) |
StringBuilder |
✅ | tipo compatível: Append(incl. bool→"True"/"False")/AppendLine("\n")/Insert/Remove/Replace/Clear/Length/ToString
|
| LINQ | ✅ | Where/Select/SelectMany/Where-Select(indexado)/OrderBy/Distinct(By)/GroupBy/ToDictionary/ToLookup/Zip/Chunk/MinBy/MaxBy/Take(While)/Skip(While)/Aggregate/Sum/Min/Max/Average/Count/Any/All/First/Last/Concat/Reverse/Join/GroupJoin/ThenBy/ThenByDescending (Join/GroupJoin = hash join que preserva a ordem sobre chaves primitivas; OrderBy+ThenBy = uma única ordenação composta estável, com a fonte copiada). O IGrouping vindo de GroupBy/ToLookup é usável como sequência (iterar, g.Select/g.Sum/g.Count()) e expõe g.Key; o indexador [key] de ILookup não é modelado. |
| Coleções | ✅ | List, Dictionary, HashSet (incl. inicializadores e .Count); compatíveis de Queue/Stack/LinkedList; família ordenada SortedSet/SortedDictionary/SortedList (enumeração ordenada por chave). Dicionários com chave de record/struct/tupla vão para $eq.collections.valueMap (chaves estruturais: construção, get/set em d[k], ContainsKey/Add/Remove/Clear/TryGetValue/GetValueOrDefault, Keys/Values/Count, foreach); dicionários com chave string/número/enum mantêm a forma de objeto simples. O indexador ILookup[key] devolve o grupo (ou vazio para uma chave ausente). |
enum |
✅ | string com o nome do membro (igualdade/switch/ternário) |
long/ulong
|
✅ | exato via BigInt (helper long); literais 5L→5n, no fio como string JSON |
DateTime |
✅ | tipo compatível DateTime com precisão de tick: construtores, componentes, Add*, -→TimeSpan, comparações, .ToString()/format; fio ISO-8601 + hidratação |
TimeSpan |
✅ | tipo compatível TimeSpan com precisão de tick: From*, construtores, componentes/totais, + -, comparações, .ToString() "c" do .NET; fio "c" + hidratação |
DateOnly / TimeOnly
|
✅ | tipos compatíveis (.NET 6+): construtores, componentes, Add*(+ volta do TimeOnly), comparações, .ToString() invariante (MM/dd/yyyy / HH:mm); fio ISO + hidratação |
DateTimeOffset |
✅ | tipo compatível com precisão de tick (hora de parede + deslocamento, comparado pelo instante): construtores, componentes, Offset/UtcDateTime/LocalDateTime, ToOffset, Add*, From/ToUnixTime*, - →TimeSpan, comparações por instante, .ToString() invariante (MM/dd/yyyy HH:mm:ss zzz); fio ISO+offset + hidratação |
record / struct / tupla de valor |
✅ |
Semântica de valor. Records/structs são objetos simples (o posicional new Point(1,2) → {x,y}, inicializadores de objeto mesclam), tuplas são arrays com acesso a elemento por posição (t.Item1) e por nome declarado ((int X, int Y).X) → índice. ==/!=, .Equals, Contains, Distinct comparam estruturalmente via $eq.equals; o with copia e substitui. A desconstrução var (a, b) = … funciona para tuplas (destructuring de array, com buracos de descarte) e records (destructuring de objeto pela ordem do Deconstruct). Records são emitidos como classes JS nomeadas, carregando os métodos de instância do usuário + um equals estrutural, um with que preserva o protótipo, e o toString do .NET; a semântica de valor não muda. O pipeline de build descobre records por varredura e emite cada um como módulo próprio; componentes que referenciam um record o importam automaticamente (reativo, sem lista fixa). Os valores do SSR são re-hidratados de volta na classe do record no cliente (recursivamente, restaurando records aninhados e membros compatíveis), então métodos/instanceof sobrevivem. Cobre records posicionais e de corpo e structs simples (a construção por inicializador de objeto mapeia para o construtor pela ordem dos membros, com padrões por membro), mais herança de record (extends + super) e records genéricos (argumentos de tipo apagados). Dicionários com chave de record (Dictionary<RecordKey, V>) vão para $eq.collections.valueMap, para que chaves iguais por valor colidam como no .NET. |
Nullable<T> (T?) |
✅ |
HasValue/Value, GetValueOrDefault() (padrão ciente do tipo: 0/false/$eq.num.dec(0)/membro zero do enum/…) e GetValueOrDefault(fallback), ??; operadores elevados via $eq.nullable.*: a aritmética propaga null, o relacional (< > <= >=) é falso quando qualquer lado é nulo (não uma coerção numérica). O GetValueOrDefault() sem argumento em DateTime?/Guid?/struct devolve null, então use a forma com fallback ali. |
Guid |
✅ |
Guid.NewGuid()→crypto.randomUUID(), Guid.Empty, Guid.Parse; fio como string |
🌐 English · Português
🏁 Comece aqui
📱 Write-once
- Componentes write-once
- Superfície declarativa
- Motor Photon
- Design System
- Capacidades
- Armazenamento
- Formulários
- Editor de código
- Markdown
- Mermaid
- Renderização de Email
🏗️ Arquitetura
⚙️ Compilação
- Compilador
- Avaliação em tempo de compilação
- Recursos C# suportados
- Resolução de tipos externos
- Fluxo de build
- Diagnósticos
⚡ Runtime
🔌 Servidor
🎨 Ecossistema
🚀 Desenvolvimento