programing

개체가 런타임에 TypeScript를 사용하여 인터페이스를 구현하는지 확인합니다.

telebox 2023. 3. 18. 08:28
반응형

개체가 런타임에 TypeScript를 사용하여 인터페이스를 구현하는지 확인합니다.

실행 시 JSON 컨피규레이션파일을 로드하고 인터페이스를 사용하여 예상되는 구조를 정의합니다.

interface EngineConfig {
    pathplanner?: PathPlannerConfig;
    debug?: DebugConfig;
    ...
}

interface PathPlannerConfig {
    nbMaxIter?: number;
    nbIterPerChunk?: number;
    heuristic?: string;
}

interface DebugConfig {
    logLevel?: number;
}

...

오토 컴플리션 등을 사용할 수 있기 때문에, 다양한 자산에 액세스 할 수 있습니다.

질문: 이 선언을 사용하여 로드하는 파일이 올바른지 확인할 수 있는 방법이 있습니까? 즉, 예기치 않은 속성을 가지고 있지 않은가?

방법은 있지만, 스스로 실장할 필요가 있습니다.이것은 "사용자 정의 유형 가드"라고 불리며 다음과 같습니다.

interface Test {
    prop: number;
}

function isTest(arg: any): arg is Test {
    return arg && arg.prop && typeof(arg.prop) == 'number';
}

실제 에서는, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」isTest기능은 전적으로 여러분에게 달려 있지만, 좋은 점은 이것이 실제 기능이라는 것입니다. 즉, 테스트 가능하다는 것입니다.

이제 런타임에 다음을 사용할 수 있습니다.isTest()오브젝트가 인터페이스를 존중하는지 여부를 확인합니다.컴파일 시 typescript는 가드를 인식하여 예상대로 후속 사용을 처리합니다.

let a:any = { prop: 5 };

a.x; //ok because here a is of type any

if (isTest(a)) {
    a.x; //error because here a is of type Test
}

상세한 것에 대하여는, https://basarat.gitbook.io/typescript/type-system/typeguard 를 참조해 주세요.

이를 위한 다른 방법을 다음에 제시하겠습니다.

ts-interface-builder는 빌드 시 TypeScript 파일에서 실행하는 도구입니다(예:foo.ts( "Descriptorfoo-ti.ts를 참조해 주세요.

ts-interface-module에서는 실행 시 오브젝트를 검증하기 위해 이러한 명령어를 사용합니다.예.

import {createCheckers} from 'ts-interface-checker';
import fooDesc from 'foo-ti.ts';
const checkers = createCheckers(fooDesc);

checkers.EngineConfig.check(someObject);   // Succeeds or throws an informative error
checkers.PathPlannerConfig.check(someObject);

하시면 됩니다.strictCheck()메서드를 사용하여 알 수 없는 속성이 없는지 확인합니다.

아니요.

현재 타입은 개발 및 컴파일 시에만 사용됩니다.유형 정보는 컴파일된 JavaScript 코드로 변환되지 않습니다.

@JasonEvans가 지적한 https://stackoverflow.com/a/16016688/318557,에서

2015년 6월 이후 TypeScript repo에 미해결 문제가 있습니다.https://github.com/microsoft/TypeScript/issues/3628

여기 좋은 방법이 있어요.typescript-json-schema를 사용하여 TypeScript 인터페이스를 JSON 스키마로 변환할 수 있습니다.

typescript-json-schema --required --noExtraProps \
  -o YOUR_SCHEMA.json YOUR_CODE.ts YOUR_INTERFACE_NAME

그런 다음 실행 시 ajv 등의 JSON 스키마 검증기를 사용하여 데이터를 검증합니다.

const fs = require('fs');
const Ajv = require('ajv');

// Load schema
const schema = JSON.parse(fs.readFileSync('YOUR_SCHEMA.json', {encoding:"utf8"}));
const ajv = new Ajv();
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
var validator = ajv.compile(schema);

if (!validator({"hello": "world"})) {
  console.log(validator.errors);
}

TypeScript는 (지혜적으로) Colly의 법칙에 준거하고 있으며, Typescript는 오브젝트 검증자가 아닌 트랜스필러라고 생각합니다.한편, 타이프 스크립트인터페이스는 (놀라운) 한정된 어휘를 가지고 있어 다른 프로그래머가 어레이 길이, 속성 수, 패턴 속성 등 오브젝트를 구별하기 위해 사용할 수 있는 쉐이프에 대해 검증할 수 없기 때문에 오브젝트 검증이 불충분하다고 생각합니다.

스크립트가 아닌 코드에서 개체를 사용할 때는 런타임 검증에 AJV와 같은 JSONshema 검증 패키지를 사용하고 JSONshema에서 TypeScript 유형 정의를 컴파일하기 위해 .d.ts 파일 생성기(: DTSgenerator 또는 DTS-generator)를 사용합니다.

주요 주의사항은 JSONschemata는 typescript(patternProperties 등)로 구분할 수 없는 쉐이프를 기술할 수 있기 때문에 JSON 스키마에서 .t.ds로의 일대일 변환이 아니며 JSON 스키마를 사용할 때 생성된 .dts 파일을 손으로 편집해야 할 수 있다는 것입니다.

즉, 다른 프로그래머가 객체 타입을 추론하기 위해 배열 길이 등의 속성을 사용할 수 있기 때문에, 나는 트랜스포일러가 다른 타입을 대신 사용하는 것을 막기 위해 TypeScript 컴파일러가 혼동을 일으킬 수 있는 타입을 구별하는 습관이 있다.

[MyTypes.yaml]

definitions: 
    type-A: 
        type: object
        properties:
            type:
                enum:
                - A
            foo: 
                type: array
                item: string
                maxLength: 2
    type-B: 
        type: object
        properties:
            type:
                enum:
                - B
            foo: 
                type: array
                item: string
                minLength: 3
        items: number

" " 가 됩니다..d.ts같은 :

[MyTypes.d.ts]

interface typeA{
    type: "A";
    foo: string[];
}

interface typeB{
    type: "B";
    foo: string[];
}

네. 이 체크는 제가 얼마 전에 출시한 향상된 버전의 TypeScript 컴파일러를 사용하여 실행 시 실행할 수 있습니다.다음과 같은 작업을 수행할 수 있습니다.

export interface Person {
    name: string;
    surname: string;
    age: number;
}

let personOk = { name: "John", surname: "Doe", age: 36 };
let personNotOk = { name: 22, age: "x" };

// YES. Now you CAN use an interface as a type reference object.
console.log("isValid(personOk):  " + isValid(personOk, Person) + "\n");
console.log("isValid(personNotOk):  " + isValid(personNotOk, Person) + "\n");

출력은 다음과 같습니다.

isValid(personOk):  true

Field name should be string but it is number
isValid(personNotOk):  false

★★★★★★★★★에 주의해 주세요.isValid함수는 재귀적으로 작동하므로 중첩된 개체를 검증하는 데도 사용할 수 있습니다.여기서 전체 작업 를 찾을 수 있습니다.

네, 그것을 하는 lib가 있습니다.https://github.com/gcanti/io-ts

아이디어는 간단하며, 오브젝트에 대한 보다 복잡한 체크로 구성된 속성에 대한 단순한 체크가 있습니다.

이 질문이 오래되었다는 것은 알지만, 저는 단지 데코레이터를 사용하여 JSON 오브젝트 및 타이프스크립트용 검증기를 작성했을 뿐입니다.
여기서 입수할 수 있습니다.ts-json-object
이 질문 이후 타이프 스크립트는 조금 바뀌어 나중에 사용할 수 있도록 타입 정보를 기록할 수 있는 실험적인 기능을 갖추고 있습니다.
에서는 검증하다@required ★★★★★★★★★★★★★★★★★」@optional검증 표기에 유형에 대한 언급이 없는 경우에도 속성뿐만 아니라 유형도 검증합니다.

예:

import {JSONObject,required,optional,lt,gte} from 'ts-json-object'

class Person extends JSONObject {
    @required // required
    name: string
    @optional // optional!
    @lt(150) // less than 150
    @gte(0) // Greater or equal to 0
    age?: number
}

let person = new Person({
 name: 'Joe'
}) // Ok
let person = new Person({
}) // Will throw a TypeError, because name is required
let person = new Person({
 name: 123
}) // Will throw a TypeError, because name must be a string

커스텀 검증 등 그 밖에도 많은 기능을 갖추고 있습니다.

lib를 답을 저는 'lib를 사용하라'는 답을 .ts-data-checker런타임에 TypeScript 언어 서비스를 실행하여 JSON을 확인합니다.

import { checker } from "ts-data-checker";

export interface PathPlannerConfig {
    nbMaxIter?: number;
    nbIterPerChunk?: number;
    heuristic?: string;
}

const { checkJson } = checker("PathPlannerConfig", "./nameofthisfile");

if (checkJson(`{ "nbMaxIter": 1 }`)) {
    console.log('valid!');
}

당신의 컨피규레이션파일이 어떻게 생겼는지 모르겠지만, 가장 확실한 것은 json 파일입니다.단, 저는 json 스키마를 사용하여 파일이 스키마에 맞는지 검증합니다.

여기 json 스키마 v4 매뉴얼이 있습니다.http://json-schema.org/documentation.html

테스트 방법 중 하나는 https://github.com/fge/json-schema-validator입니다.

물론 인터페이스를 기반으로 스키마를 작성해야 하지만 직접 사용할 수는 없습니다.

클래스 검증을 사용할 수 있습니다.

  1. 인터페이스를 클래스로 바꿉니다.

클래스 Cat {@IsNotEmpty() 이름: 문자열;}    
// 정적 타이핑이 작동합니다!const cat: 고양이 = {이름: "Barsik"};
  1. 검증 함수를 만듭니다.예:

"class-validator"에서 {validateSync} Import;    
데이터 입력 = {[key: string]:};    
// 새 클래스 인스턴스를 만들고 "class-validator"를 통해 검증합니다.export const validate = <D는 데이터를 확장하고 C는 {new(): D}를 확장합니다.(데이터: D, 클래스)템플릿:C): 부울 => {const instanceClass = 새 클래스템플릿();Object.keys(데이터).각((키) => {instanceClass[key] = 데이터[key];
});!validateSync(instanceClass)를 반환합니다.길이}
  1. 정적 입력에는 인터페이스 대신 클래스, 유효성 확인에는 클래스 사용

(validate(cat, Cat)) {// OK(확인)} 기타 {// 오류}

언급URL : https://stackoverflow.com/questions/33800497/check-if-an-object-implements-an-interface-at-runtime-with-typescript

반응형