区分 类 的联合
Discriminating A Union of Classes
使用 Typescript 3.4 我试图根据位于每个子类上的单个只读字段(鉴别器)来区分 typescript 的并集 类;本身看起来很简单,但我似乎无法解决它。
下面是一个 link 的游乐场,其中 createFruit 方法应该能够采用通用参数来通过鉴别器过滤下一个 属性。任何见解将不胜感激;但是,它似乎允许评估为 never。
abstract class Fruit {
abstract readonly fruitType: string;
}
class Banana extends Fruit {
fruitType = 'banana';
length = 2;
color = 'yellow';
}
class Pear extends Fruit {
fruitType = 'pear';
roundness = 'very round';
}
class Apple extends Fruit {
fruitType = 'apple';
fallOfMan = true;
hasWorms = true;
}
type KnownFruits = Banana | Pear | Apple;
type FruitTypes = KnownFruits['fruitType'];
type FruitDiscriminator<T extends FruitTypes> = Extract<KnownFruits, { fruitType: T }>;
let createFruit = <T extends FruitTypes>(fruitType: T, props: FruitDiscriminator<T>) => { }
createFruit('pear', {} ) // Argument of type '{}' is not assignable to parameter of type 'never'.
问题是派生的 类 中的 fruitType
是 string
类型,而不是与字符串文字关联的字符串文字类型。在初始化字段时,Typescript 默认将文字类型扩展为基本类型。要解决此问题,您可以使用 as const
断言,或使 w 字段 readonly
(或手动指定字符串文字类型,但这将复制字符串)
readonly
解决方案最有意义,因为类型不应更改:
abstract class Fruit {
abstract readonly fruitType: string;
}
class Banana extends Fruit {
readonly fruitType = 'banana';
length = 2;
color = 'yellow';
}
class Pear extends Fruit {
readonly fruitType = 'pear';
roundness = 'very round';
}
class Apple extends Fruit {
readonly fruitType = 'apple';
fallOfMan = true;
hasWorms = true;
}
type KnownFruits = Banana | Pear | Apple;
type FruitTypes = KnownFruits['fruitType'];
type FruitDiscriminator<T extends FruitTypes> = Extract<KnownFruits, { fruitType: T }>;
let createFruit = <T extends FruitTypes>(fruitType: T, props: FruitDiscriminator<T>) => { }
// ok
createFruit('pear', {
fruitType: 'pear',
roundness: ""
})
使用 Typescript 3.4 我试图根据位于每个子类上的单个只读字段(鉴别器)来区分 typescript 的并集 类;本身看起来很简单,但我似乎无法解决它。
下面是一个 link 的游乐场,其中 createFruit 方法应该能够采用通用参数来通过鉴别器过滤下一个 属性。任何见解将不胜感激;但是,它似乎允许评估为 never。
abstract class Fruit {
abstract readonly fruitType: string;
}
class Banana extends Fruit {
fruitType = 'banana';
length = 2;
color = 'yellow';
}
class Pear extends Fruit {
fruitType = 'pear';
roundness = 'very round';
}
class Apple extends Fruit {
fruitType = 'apple';
fallOfMan = true;
hasWorms = true;
}
type KnownFruits = Banana | Pear | Apple;
type FruitTypes = KnownFruits['fruitType'];
type FruitDiscriminator<T extends FruitTypes> = Extract<KnownFruits, { fruitType: T }>;
let createFruit = <T extends FruitTypes>(fruitType: T, props: FruitDiscriminator<T>) => { }
createFruit('pear', {} ) // Argument of type '{}' is not assignable to parameter of type 'never'.
问题是派生的 类 中的 fruitType
是 string
类型,而不是与字符串文字关联的字符串文字类型。在初始化字段时,Typescript 默认将文字类型扩展为基本类型。要解决此问题,您可以使用 as const
断言,或使 w 字段 readonly
(或手动指定字符串文字类型,但这将复制字符串)
readonly
解决方案最有意义,因为类型不应更改:
abstract class Fruit {
abstract readonly fruitType: string;
}
class Banana extends Fruit {
readonly fruitType = 'banana';
length = 2;
color = 'yellow';
}
class Pear extends Fruit {
readonly fruitType = 'pear';
roundness = 'very round';
}
class Apple extends Fruit {
readonly fruitType = 'apple';
fallOfMan = true;
hasWorms = true;
}
type KnownFruits = Banana | Pear | Apple;
type FruitTypes = KnownFruits['fruitType'];
type FruitDiscriminator<T extends FruitTypes> = Extract<KnownFruits, { fruitType: T }>;
let createFruit = <T extends FruitTypes>(fruitType: T, props: FruitDiscriminator<T>) => { }
// ok
createFruit('pear', {
fruitType: 'pear',
roundness: ""
})