typescript “as const”与类型结合使用?

bprjcwpo  于 2022-12-30  发布在  TypeScript
关注(0)|答案(3)|浏览(213)

我想把常量的类型和使用它"as const"来获取文本类型作为类型结合起来:

type MyType = {name: string};

const x:MyType = {
    name: 'test' // Autocompleted, typesafe. But Type is {name: string}, not 
                 // what I want, {name: 'test'}
}

const x = { name: 'test' } as const; // Gives correct type, but no type check...

如何做到这一点?

lymnna71

lymnna711#

编辑2022年9月:

在Typescript 4.9中,我们现在可以使用satisfies运算符:

type MyType = { name: string }

const x ={
  name: 'test', // Autocompleted, typesafe
} as const satisfies MyType

x.name // type is 'test' (not string)

如果由于某种原因,您不能使用satisfies,那么复制相同的行为是相当容易的:

/**
 * Replacement for TS statisfies operator, until it's well supported
 * Usage:
 * const test = satisfy<{ a: string }>()({ a: 'test', b: 'test' })
 * */
export function satisfy<TSatisfied>(): <T extends TSatisfied>(value: T) => T {
  return (value) => value
}

以前的解决方案:

以下是实现您所需的方法:

type MyType = { name: string }

// This function does nothing. It just helps with typing
const makeMyType = <T extends MyType>(o: T) => o

const x = makeMyType({
  name: 'test', // Autocompleted, typesafe
} as const)

x.name // type is 'test' (not string)
xxhby3vn

xxhby3vn2#

不需要对{name: "test"} as const进行类型检查,因为Typescript使用结构相等,这意味着只要{name: "test"} as const是MyType的相同结构,它们就相等,因此相同。
使用这些辅助类型可以观察到这种行为。

interface MyType {
     name: string;
}
const test = {name: "test"} as const;
type IsEqual<T, U> = [T] extends [U] ? true : false;
type AreTheyEqual = IsEqual<typeof test, MyType> // true they are the same.

任何接受MyType的东西都可以接受Test类型。
编辑:如果你想强制test为MyType类型,以在那里对test进行类型检查,你不能通过保留字符串文字来做到这一点,因为任何Assert为MyType的东西都将失去文字类型,并退回到字符串。

type MyType = {name: string};
const x:MyType = {
    name: 'test' as const
}
type Test = typeof x["name"] // string;

这意味着如果你想在MyType上同时拥有Literal和string类型,你需要做一些类似的事情(改变MyType)。注意使用这个看起来很冗长,但是可以说比“as const”更简单。

interface MyType<NAME extends string = string> {
    name: NAME;
}
const x: MyType = {
    name: 'test' // string;
}
const y: MyType<"test"> = {
    name: "test" // "test"
}

type Test1 = typeof x["name"]// string;
type Test = typeof y["name"] // "test";

^允许字符串和文本类型。

biswetbf

biswetbf3#

我不认为有任何原语支持。但是你可以通过定义另一个带有类型Assert的常量来做类型检查。

type MyType = {name: string};

const x = {
    name: 'test' 
} as const

const xTypeCheck = typeof (x as MyType) // Check the type of x as MyType

注意:我使用'typeof'来避免引用x的值,这确保了如果没有任何其他引用,x的值可以被删除。

相关问题