老实说,我不知道我的设置是否有问题或这是否是打字稿功能。在以下示例中:
type AllowedChars = 'x' | 'y' | 'z';
const exampleArr: AllowedChars[] = ['x', 'y', 'z'];
function checkKey(e: KeyboardEvent) {
if (exampleArr.includes(e.key)) { // <-- here
// ...
}
}
打字稿编译器抱怨Argument of type 'string' is not assignable to parameter of type 'AllowedChars'.
,但是我应该分配给哪里? Array.prototype.includes
返回一个布尔值(我没有存储)。我可以通过类型断言来使错误保持沉默,如下所示:
if (exampleArr.includes(e.key as AllowedChars)) {}
但是这是正确的,我正在接受用户输入,可能是任何东西。我不明白为什么检查数组中是否存在 的函数(Array.prototype.includes()
)应该了解预期的输入类型。
我的tsconfig.json
(打字稿v3.1.3):
{
"compilerOptions": {
"target": "esnext",
"moduleResolution": "node",
"allowJs": true,
"noEmit": true,
"strict": true,
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "preserve",
},
"include": [
"src"
],
"exclude": [
"node_modules",
"**/__tests__/**"
]
}
任何帮助将不胜感激!
答案 0 :(得分:3)
是的,从技术上讲,应该允许import React from 'react';
import {
StyleSheet,
ScrollView,
Image,
Dimensions } from 'react-native'
import { ImagePicker, Permissions } from 'expo'
import { Icon } from 'native-base'
import Amplify from '@aws-amplify/core'
import Storage from '@aws-amplify/storage'
import config from './aws-exports'
class App extends React.Component {
state = {
image: null,
}
// fetch a single image from user's device and save it to S3
useLibraryHandler = async () => {
await this.askPermissionsAsync()
let result = await ImagePicker.launchImageLibraryAsync(
{
allowsEditing: false,
//aspect: [4, 3],
}
)
console.log(result);
if (!result.cancelled) {
this.setState({ image: result.uri })
this.uploadImage(this.state.image)
}
}
// add a single image to S3
uploadImage = async uri => {
const response = await fetch(uri)
const blob = await response.blob() // format the data for images
const folder = 'images'
const fileName = 'flower.jpeg'
await Storage.put(folder + '/' + fileName, blob, {
contentType: 'image/jpeg',
level: 'public'
}).then(data => console.log(data))
.catch(err => console.log(err))
}
render() {
let { image } = this.state
let {height, width} = Dimensions.get('window')
return (
<ScrollView style={{flex: 1}} contentContainerStyle={styles.container}>
<Icon
name='md-add-circle'
style={styles.buttonStyle}
onPress={this.useLibraryHandler}
/>
{/*
true && expression always evaluates to expression,
and false && expression always evaluates to false
*/}
{image &&
<Image source={{ uri: image }} style={{ width: width, height: height/2 }} />
}
</ScrollView>
);
}
}
中的searchElement
参数为Array<T>.includes()
的超类型,但是standard TypeScript library declaration假定它只是{{ 1}}。在大多数情况下,这是一个很好的假设,因为您通常不需要像@GustavoLopes所提到的那样完全比较不相关的类型。但是您的类型不是完全无关的吗?
有不同的处理方法。您所做的断言可能是最不正确的断言,因为您断言T
是T
,尽管可能并非如此。它“完成了工作”,但是您对此感到不安是正确的。
另一种方法是通过declaration merging在本地重写标准库以接受超类型,这有点复杂并且使用conditional types:
string
然后您的原始代码就可以使用:
AllowedChars
同时仍然阻止比较完全不相关的类型:
// remove "declare global" if you are writing your code in global scope to begin with
declare global {
interface Array<T> {
includes<U extends (T extends U ? unknown : never)>(searchElement: U, fromIndex?: number): boolean;
}
}
但是处理此问题的最简单但仍然正确的方法是将if (exampleArr.includes(e.key)) {} // okay
// call to includes inspects as
// (method) Array<AllowedChars>.includes<string>(searchElement: string, fromIndex?: number | undefined): boolean (+1 overload)
的类型扩展为if (exampleArr.includes(123)) {} // error
// Argument of type '123' is not assignable to parameter of type 'AllowedChars'.
:
exampleArr
或更简洁地说:
string[]
通向const stringArr: string[] = exampleArr; // no assertion
if (stringArr.includes(e.key)) {} // okay
只是“有点”正确,因为为方便起见,TypeScript不安全地将{{1}中的if ((exampleArr as string[]).includes(e.key)) {} // okay
视为string[]
中的covariant。这很适合阅读,但是在编写属性时会遇到问题:
Array<T>
但是由于您只是从数组中读取数据,因此非常安全。
好的,希望其中之一对您有所帮助。祝你好运!
答案 1 :(得分:0)
如果您要比较两种不同的类型,那么它们自然是不同的。
想象你有:
type A = {paramA: string};
type B = {paramB: number};
const valuesA: A[] = [{paramA: 'whatever'}];
const valueB: B = {paramB: 5};
valuesA.includes(valueB); // This will always be false, so it does not even make sense
在您的情况下,编译器威胁AllowedChars
是与string
完全不同的类型。您必须将收到的string
“投射”到AllowedChars
。
但是这是正确的吗,我正在接受可能是任何东西的用户输入。
编译器不知道您要使用includes
完成什么工作。它只知道它们具有不同的类型,因此不应进行比较。