foo
变量应保留{ a: { b: string } }
推断类型,同时限制其他类型Foo
。它最好应该有类型{ a: { b: string } } & Foo
:
type Foo = { [k: string]: { [k: string]: string } };
const _foo = { a: { b: 'c' } };
export const foo: typeof _foo & Foo = _foo;
但它可以接受{ a: { b: string } }
类型 - 只要它不符合Foo
就会产生类型错误:
type Foo = { [k: string]: { [k: string]: string } };
function checkFoo(foo: Foo) {};
let foo = { a: { b: 'c' } };
checkFoo(foo);
目标是使TypeScript仅发出单个JavaScript行:
var foo = { a: { b: 'c' } };
checkFoo
函数也可以出现在编译器输出中,只要它没有被调用,所以它可以被minifier删除为死代码。
如果可能的话,我更愿意避免像checkFoo(foo)
这样的不必要的编译器输出。
这里有什么选择?是否有特定于最新TypeScript版本2.7和2.8的那些?
答案 0 :(得分:3)
虽然我不一定同意不惜一切代价避免额外函数调用的前提,但如果foo
未实现预期的接口而不使用,我们可以生成不发出JS代码的编译器错误功能。
该方法基于创建条件类型(2.8中提供),该类型根据常量的类型是否实现接口返回不同的字符串文字类型。然后我们可以在我们期望特定类型文字的地方使用此类型。
要获得错误,我们需要以不产生代码的方式使用该类型,并且我在声明或类型别名中找到了两种可能的方法。
export type Foo = { [k: string]: { [k: string]: string } };
type TestType<T, TBase> = T extends TBase ? "OK" : "Implementation does not extend expected type";
type Validate<T extends "OK"> = "OK";
let foo = { a: { b: 'c' } };
// use type in a constant
declare const fooTest : Validate<TestType<typeof foo, Foo>> // ok
// use type in a type alias
type fooTest = Validate<TestType<typeof foo, Foo>> //ok
let fooBad = { a: { b: 10 } };
declare const fooBadTest : Validate<TestType<typeof fooBad, Foo>>; // error: Type '"Implementation does not extend expected type"' does not satisfy the constraint '"OK"'
type fooBadTest = Validate<TestType<typeof fooBad, Foo>> // error: Type '"Implementation does not extend expected type"' does not satisfy the constraint '"OK"'.
这种方法的一个问题是我们必须引入污染名称空间的额外类型别名/常量名称。
游乐场link。
答案 1 :(得分:2)
你可以写一个函数:
function makeFoo<T extends Foo>(x: T): T & Foo {
return x as T & Foo;
}
// OK, foo: what you want
export const foo = makeFoo({ a: { b: 'c' } });
// Error
export const bar = makeFoo({ a: { b: 12 } });
答案 2 :(得分:1)
使用与this answer中描述的方法类似的方法可以避免不必要的输出:
type Foo = { [k: string]: { [k: string]: string } };
type CheckFoo<T extends Foo> = T;
let foo = { a: { b: 'c' } };
type _checkFoo = CheckFoo<typeof foo>; // produces an error if foo isn't compatible