TypeScript(^ 2.3.3)是否会丢失有关数组传播的类型信息?

时间:2017-06-07 20:10:49

标签: arrays typescript

当我使用数组扩展运算符创建新数​​组时 TypeScript似乎丢失了正确的类型信息

如果我使用Array.combine()创建新数组,则不会发生这种情况。

我准备了一个简单的例子来证明这一点。我使用声明合并使常量(ACESTWOS等)具有相应的类型。然后我创建类型Category为"超类型"。

变量sectionsSpread在使用数组扩展运算符创建后属于string[]类型。变量sectionsCombined的类型为Category[]

我预计变量sectionsSpread也属于Category[]类型。

这是一个错误吗?我有阵列传播错误吗?

const ACES = 'ACES';
type ACES = typeof ACES;

const TWOS = 'TWOS';
type TWOS = typeof TWOS;

const THREES = 'THREES';
type THREES = typeof THREES;

const FULL_HOUSE = 'FULL_HOUSE';
type FULL_HOUSE = typeof FULL_HOUSE;

const SMALL_STRAIGHT = 'SMALL_STRAIGHT';
type SMALL_STRAIGHT = typeof SMALL_STRAIGHT;

const LARGE_STRAIGHT = 'LARGE_STRAIGHT';
type LARGE_STRAIGHT = typeof LARGE_STRAIGHT;

type Category = ACES | TWOS | THREES |
    FULL_HOUSE | SMALL_STRAIGHT | LARGE_STRAIGHT;

const upperSection: Array<Category> = [ACES, TWOS, THREES];
const lowerSection: Array<Category> = [FULL_HOUSE, SMALL_STRAIGHT, LARGE_STRAIGHT]; 

const sectionsSpread = [
    ...upperSection,
    ...lowerSection
];

const sectionsCombined = upperSection.concat(lowerSection);

UDATE

@dbandstra和@basarat指出了我正确的方向。阅读suggested blog post后,我认为我理解文字类型扩展。但是,对于我来说,这仍然无法解释typeof运营商在此背景下的行为。

我希望以下示例能让我的问题更清晰:

const ACES = 'ACES';
type ACES = 'ACES'; // non-widening literal type 

const TWOS = 'TWOS';
type TWOS = 'TWOS'; // non-widening literal type

type Category = ACES | TWOS; // are these values or types?

const upperSection: Category[] = [ACES]; 
const lowerSection: Category[] = [TWOS];

const sectionsSpread = [
    ...upperSection,
    ...lowerSection,
]; // is of type Category[]

如果我使用typeof,则变量sectionsSpread最终会变为string[]类型:

const ACES = 'ACES';
type ACES = typeof ACES; // what does typeof do here?

const TWOS = 'TWOS';
type TWOS = typeof TWOS; // what does typeof do here?

type Category = ACES | TWOS; // are these values or types?

const upperSection: Category[] = [ACES]; 
const lowerSection: Category[] = [TWOS];

const sectionsSpread = [
    ...upperSection,
    ...lowerSection,
]; // is of type string[]

1 个答案:

答案 0 :(得分:2)

这是扩大与非扩大。显式注释意味着在分配给其他值时,TypeScript不会更改其含义。

加宽:

const ACES = 'ACES';
type Category = typeof ACES;

const upperSection: Category[] = []; 

const sectionsSpread = [
    ...upperSection,
]; // string[]

非扩展:

const ACES = 'ACES';
type Category = 'ACES';

const upperSection: Category[] = []; 

const sectionsSpread = [
    ...upperSection,
]; // Category