2017-09-05 1 views
3

Es scheint, dass TypeScript (der letzten Version) manchmal keine Unionstypen eingrenzen kann, selbst wenn ein Typschutz vorhanden ist. Ist dieses Verhalten ein Bug oder ein Feature:Fehlfunktion des Typs "type" -Unionstypenfehler

Präambel:

// some config 
interface Config { 
    name: string; 
    option1?: number; 
    option2?: boolean; 
} 

// arbitrary type 
interface Entity { 
    a: number; 
    b: number; 
} 

// name aware type guard for entity property-to-config map 
// some default config may be replaced with a property name 
type TConfigSet<TData> = { 
    [P in keyof TData]: (Config & { name: P }) | P; 
} 

// example of TConfigSet usage 
const EntityConfigs: TConfigSet<Entity> = { 
    a: { 
     name: 'a', 
     option2: true 
    }, 
    b: 'b' 
} 

Frage:

// this function compiles 
function TypeLooseFieldToName(name: string | Config): string { 
    if (typeof name === 'string') return name; 
    else return name.name; 
} 

// this one doesn't 
function TypeStrictFieldToName<TData>(name: keyof TData | { name: keyof TData }): keyof TData { 
    if (typeof name === 'string') return name; 
    else return name.name; // still keyof TData | { name: keyof TData }, should be shrinked to { name: keyof TData } 
} 

Antwort

1

Es scheint ein Fehler in dem Typprüfer zu sein, weil das Typoskript Handbuch sagt

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

Als Abhilfe kann der Typ-Schutz invertiert werden zunächst die benutzerdefinierten Typ auszuschließen:

function hasName(obj: string | { name: string }): obj is { name: string } { 
    return typeof obj.name === 'string'; 
} 

function getName<TData>(name: keyof TData | { name: keyof TData }): keyof TData { 
    if (hasName(name)) return name.name; 
    else return name; 
} 

// compiles with valid keys 
getName<Entity>('a'); 
getName<Entity>({ name: 'a' }); 

// doesn't compile with invalid keys 
getName<Entity>('z'); 
getName<Entity>({ name: 'z' }); 

Sie könnten das Typoskript Probleme in GitHub suchen und ein neues Problem, wenn diese hasn Datei ‚t bereits früher angesprochen:

https://github.com/Microsoft/TypeScript/issues

+0

Sie waren richtig, dies ist ein Fehler in 2.6 festgelegt werden –

0

typeof name === 'string' nicht für keyof TData als Typ-Schutz arbeiten, weil anscheinend string und keyof TData angenommen werden zwei verschiedene Typen vom Compiler. Wenn Sie Ihre eigene Schutzvorrichtung für keyof TData hinzufügen funktioniert es: „a. keyof T Typ ein Subtyp von string betrachtet wird“

function TypeStrictFieldToName<TData>(name: keyof TData | { name: keyof TData }): keyof TData { 
    if (isKeyofTData<TData>(name)) return name; 
    else return name.name; // type of name here is { name: keyof TData } 
} 

function isKeyofTData<TData>(name: keyof TData | {}): name is keyof TData { 
    return typeof name === 'string'; 
}